Slow performance fix oracle alert log v$diag_alert_ext x$diag_alert_ext

港控/mmm° 2023-10-18 23:55 175阅读 0赞

Slow performance fix oracle alert log v$diag_alert_ext x$diag_alert_ext

v$diag_alert_ext aka x$diag_alert_ext should be useful for querying the oracle alert log. Unfortunately with comon conditions in the where clause, queries against it run unusably slow.

This is covered in Mos doc 1684140.1 “Selects from v$diag_alert_ext run slowly with large alert logs“, but that ends with the unhelpful “Solution: There is no solution.“. Bug 18643828 is an (unactioned) enhancement request from 2014 to add indexes to x$diag_alert_ext.

But actually there is a solution already – the below script runs fast on all databases I’ve tested it on so far

  1. -- 1) Initial setup, one-off.
  2. CREATE GLOBAL TEMPORARY TABLE gtt_diag_alert_ext (
  3. host_id VARCHAR2(67)
  4. , originating_timestamp TIMESTAMP(9) WITH TIME ZONE
  5. , message_type VARCHAR2(14)
  6. , message_level VARCHAR2(9)
  7. , message_text VARCHAR2(2051)
  8. ) ON COMMIT DELETE ROWS
  9. ;
  10. -- 2) Query script
  11. TRUNCATE TABLE gtt_diag_alert_ext t ; -- only needed if not connecting as a new session.
  12. INSERT INTO gtt_diag_alert_ext t ( t.host_id , t.originating_timestamp , t.message_type , t.message_level , t.message_text )
  13. SELECT d.host_id
  14. , d.originating_timestamp
  15. , CASE d.message_type
  16. WHEN 1 THEN 'Unknown'
  17. WHEN 2 THEN 'Incident Error'
  18. WHEN 3 THEN 'Error'
  19. WHEN 4 THEN 'Warning'
  20. WHEN 5 THEN 'Notification'
  21. WHEN 6 THEN 'Trace'
  22. END AS message_type
  23. , CASE d.message_level
  24. WHEN 1 THEN 'Critical'
  25. WHEN 2 THEN 'Severe'
  26. WHEN 8 THEN 'Important'
  27. WHEN 16 THEN 'Normal'
  28. END AS message_level
  29. , d.message_text
  30. FROM v$diag_alert_ext d
  31. WHERE d.originating_timestamp > SYSTIMESTAMP - 1
  32. ;
  33. SELECT t.originating_timestamp
  34. , t.host_id
  35. , t.message_type
  36. , t.message_level
  37. , t.message_text
  38. FROM gtt_diag_alert_ext t
  39. WHERE t.message_text LIKE '%ORA-%'
  40. ORDER BY t.originating_timestamp DESC
  41. ;

A real table could be used instead of a global temporary table, especially if you wanted to persist the results or centralise them into a single remote database. From v18.1, a private temporary table could be used instead. A pl/sql array or even simple pl/sql loop would also work. I found that ordered_predicates and with clause materialize hints did not fix performance in my testing.

Other columns in v$diag_alert_ext might be useful to output also, such as component_id and module_id.

Be aware v$diag_alert_ext is undocumented and hence unsupported, it relies on automatic diagnostic repository (ADR) working correctly, which might not always be the case especially in upgraded databases with non-standard directory locations or symbolic links – so worth checking there is data in v$diag_alert_ext before relying on this. Parsing alert log file on OS is likely a safer option, using old style cron scripts or newer filebeat/logstash for visualisations. Obtaining the data from the central OEM repository tables is another alternative.

August 23, 2018
Posted in Scripts

  • RobKsays:

    27 August 2018 at 15:09

    Hello!

    A had similar problem with our monitoring using v$diag_alert_ext.
    Reading your article and testing your advice I realised that select on v$diag_alert_ext is fast when you have a simple filter like originating_timestamp > SYSTIMESTAMP – 1

    It becomes slow when adding more complex criteria such as: originating_timestamp > systimestamp-301/(24*60*60)
    or and message_text not like ‘%(ORA-3136)%’.

    So the easiest solution is to use an inline view and making sure no merging or predicate pushing is taking place.

    With the with clause and a hint a real-life monitoring query looks like this:

    with oneday as (select /*+ materialize */ * from v$diag_alert_ext where ORIGINATING_TIMESTAMP>systimestamp-1)
    select to_char(ORIGINATING_TIMESTAMP,’YYYY-MM-DD HH24:MI:SS’) || ‘ ‘ || message_text from oneday
    where ORIGINATING_TIMESTAMP>systimestamp-301/(24*60*60) and message_text like ‘%ORA-%’ and message_text not like ‘%result of ORA-609%’ and message_text not like ‘%result of ORA-28%’ and message_text not like ‘%(ORA-3136)%’ and message_text not like ‘%ORA-01013:%’;

    This is fast and quick, no object needs to be created.
    I think it is an improved version of your original idea.

    Thanks for the hint. I’ve been struggling with this for quite some time.
    Cheers,
    Robert

发表评论

表情:
评论列表 (有 0 条评论,175人围观)

还没有评论,来说两句吧...

相关阅读

    相关 mysql-slow.log-清理

    mysql慢查询日志     作为运维人员,磁盘空间也是监控中重要的一个环节,数据库服务器磁盘空间不足告警,有时候不是因为业务数据量大,而是因为开启了慢查询,如果my.c