Oracle - v$lock查詢慢原因分析


 數據庫內部對象X$統計信息過舊,導致v$lock查詢慢

前段時間用python寫了個zabbix監控腳本,里面有一個檢查鎖的sql語句,sql語句是這樣子的
select count(*) retvalue from v$lock where type in('TM', 'TX') and ctime > 600;
但是zabbix界面顯示這條語句超時,zabbix超時時間默認是3s,我將其改為15s,竟然還是超時,看樣子要仔細研究這個sql語句了。
這一看不得了,這條語句執行用了18s,統計v$lock的行數竟然要7min之久,這明顯無法接受。

SQL> select count(*) retvalue from v$lock where type in('TM', 'TX') and ctime > 600;

  RETVALUE
----------
         0

Elapsed: 00:00:18.82

 

查看其執行計划

SQL> select * from table(dbms_xplan.display_cursor());

---------------------------------------------------------------------------
| Id  | Operation               | Name       | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |            |       |       |     1 (100)|
|   1 |  SORT AGGREGATE         |            |     1 |    53 |            |
|*  2 |   HASH JOIN             |            |     1 |    53 |     0   (0)|
|   3 |    MERGE JOIN CARTESIAN |            |     1 |    41 |     0   (0)|
|*  4 |     FIXED TABLE FULL    | X$KSUSE    |     1 |    19 |     0   (0)|    
|   5 |     BUFFER SORT         |            |     1 |    22 |     0   (0)|
|*  6 |      FIXED TABLE FULL   | X$KSQRS    |     1 |    22 |     0   (0)|    
|   7 |    VIEW                 | GV$_LOCK   |    10 |   120 |     0   (0)|
|   8 |     UNION-ALL           |            |       |       |            |
|*  9 |      FILTER             |            |       |       |            |
|  10 |       VIEW              | GV$_LOCK1  |     2 |    24 |     0   (0)|
|  11 |        UNION-ALL        |            |       |       |            |
|* 12 |         FIXED TABLE FULL| X$KDNSSF   |     1 |    77 |     0   (0)|    
|* 13 |         FIXED TABLE FULL| X$KSQEQ    |     1 |    77 |     0   (0)|    
|* 14 |      FIXED TABLE FULL   | X$KTADM    |     1 |    77 |     0   (0)|    
|* 15 |      FIXED TABLE FULL   | X$KTATRFIL |     1 |    77 |     0   (0)|    
|* 16 |      FIXED TABLE FULL   | X$KTATRFSL |     1 |    77 |     0   (0)|    
|* 17 |      FIXED TABLE FULL   | X$KTATL    |     1 |    77 |     0   (0)|    
|* 18 |      FIXED TABLE FULL   | X$KTSTUSC  |     1 |    77 |     0   (0)|    
|* 19 |      FIXED TABLE FULL   | X$KTSTUSS  |     1 |    77 |     0   (0)|    
|* 20 |      FIXED TABLE FULL   | X$KTSTUSG  |     1 |    77 |     0   (0)|    
|* 21 |      FIXED TABLE FULL   | X$KTCXB    |     1 |    77 |     0   (0)|    
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("SADDR"="S"."ADDR" AND
              TO_CHAR(USERENV('INSTANCE'))||RAWTOHEX("RADDR")=TO_CHAR("R"."INST_ID")||
              RAWTOHEX("R"."ADDR"))
   4 - filter("S"."INST_ID"=USERENV('INSTANCE'))
   6 - filter(("R"."KSQRSIDT"='TM' OR "R"."KSQRSIDT"='TX'))
   9 - filter(USERENV('INSTANCE') IS NOT NULL)

 

統計v$lock的行數

SQL> select count(*) from v$lock;

  COUNT(*)
----------
       600

Elapsed: 00:07:46.84  

這條語句的執行計划與上面的一樣,這里我就不貼出來了

v$lock只有600行,怎么會執行時間這么久,通過v$session能看到這條語句的等待事件為"direct path read temp"
該等待事件表示服務器進程直接讀取臨時表空間的數據,通常由臨時表太大造成。從上面的執行計划中可以看出臨時表很大的原因可能是"MERGE JOIN CARTESIAN"。
"MERGE JOIN CARTESIAN"表示笛卡爾聯接,如果兩表的行數都不小的話,這的確會造成臨時表過大。查看X$KSUSE,X$KSQRS的行數

SQL> select count(*) from X$KSUSE;                                                  

  COUNT(*)
----------
      4544

SQL> select count(*) from X$KSQRS;

  COUNT(*)
----------
     20224

 這幾千和幾萬來個笛卡爾積就是幾千萬的臨時數據了,而我的pga只有4g,pga不夠所以就用到了臨時表空間進行表關聯,也就造成了等待事件,所以說這條語句慢的主因就是這個笛卡兒積。

這條語句之前執行都好好的,為什么現在慢了呢,最可能的情況是統計信息過舊,因為自動統計信息收集job不會收集固定對象也就是X$表的統計信息。

 

收集下固定對象的統計信息

SQL> begin
     dbms_stats.gather_fixed_objects_stats;
     end;
     /

PL/SQL procedure successfully completed.  

 

再執行以下語句,可以看到執行時間0.1s都不到,而且執行計划也恢復正常,趕緊在我這邊的生產庫把類似問題進行處理,嘿嘿。

SQL> select count(*) from v$lock;

  COUNT(*)
----------
       600

Elapsed: 00:00:00.08

SQL> select * from table(dbms_xplan.display_cursor());

---------------------------------------------------------------------------------------
| Id  | Operation                | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |            |       |       |    29 (100)|          |
|   1 |  SORT AGGREGATE          |            |     1 |    36 |            |          |
|   2 |   HASH JOIN              |            |  3034 |   106K|    29 (100)| 00:00:01 |
|   3 |    HASH JOIN             |            |    15 |   360 |    23 (100)| 00:00:01 |
|   4 |     VIEW                 | GV$_LOCK   |    15 |   180 |    22 (100)| 00:00:01 |
|   5 |      UNION-ALL           |            |       |       |            |          |
|   6 |       FILTER             |            |       |       |            |          |
|   7 |        VIEW              | GV$_LOCK1  |     7 |    84 |    15 (100)| 00:00:01 |
|   8 |         UNION-ALL        |            |       |       |            |          |
|   9 |          FIXED TABLE FULL| X$KDNSSF   |     1 |    16 |     1 (100)| 00:00:01 |
|  10 |          FIXED TABLE FULL| X$KSQEQ    |     6 |   102 |    14 (100)| 00:00:01 |
|  11 |       FIXED TABLE FULL   | X$KTADM    |     1 |    20 |     5 (100)| 00:00:01 |
|  12 |       FIXED TABLE FULL   | X$KTATRFIL |     1 |    14 |     0   (0)|          |
|  13 |       FIXED TABLE FULL   | X$KTATRFSL |     1 |    14 |     0   (0)|          |
|  14 |       FIXED TABLE FULL   | X$KTATL    |     1 |    20 |     0   (0)|          |
|  15 |       FIXED TABLE FULL   | X$KTSTUSC  |     1 |    14 |     0   (0)|          |
|  16 |       FIXED TABLE FULL   | X$KTSTUSS  |     1 |    16 |     0   (0)|          |
|  17 |       FIXED TABLE FULL   | X$KTSTUSG  |     1 |    14 |     0   (0)|          |
|  18 |       FIXED TABLE FULL   | X$KTCXB    |     1 |    18 |     1 (100)| 00:00:01 |
|  19 |     FIXED TABLE FULL     | X$KSUSE    |  4544 | 54528 |     1 (100)| 00:00:01 |
|  20 |    FIXED TABLE FULL      | X$KSQRS    | 20224 |   237K|     5 (100)| 00:00:01 |
---------------------------------------------------------------------------------------

 

總結:
1.一些動態性能視圖v$查詢很慢的話,可能是由於動態性能視圖所查詢的內部對象表x$統計信息過舊,cbo選擇了錯誤的執行計划造成。
2.自動統計信息收集job不會收集內部對象表的統計信息,所以需要dba定時手工收集,或者是自己創建個job定期執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM