Oracle某行系統SQL最佳化(案例四)
問題說明:
業務人員反饋電信跑批速度慢,單條SQL耗時2s左右。 而聯通和移動跑批速度正常,但條SQL耗時不超過0.2s。
環境說明:
DB:Oracle 11.2.0.4.0 RAC OS:AIX 7.1
問題分析:
快、慢SQL文字如下:
慢SQL:
--電信1.6-1.8秒 select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '2' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime) where rownum <= 40;
快SQL:
--聯通0.1-0.2秒 select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '1' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime) where rownum <= 40;
可以看到,執行快慢兩個SQL,只有xxxxxno條件值取值不同,其他條件相同。
其中慢的SQL,條件為xxxxxno = '2',快的SQL,條件為xxxxxno = '1'。
那麼猜測,一定是慢的SQL條件為xxxxxno = '2'時結果集比快的SQL大,所有速度才慢的,需要檢查xxxxxno不同取值下結果集大小。
---資料量: 74418(慢SQL)
select count(*) from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '2' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime)
---資料量:411628(快SQL)
select count(*) from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '1' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime)
疑惑1?
慢SQL的結果集有74418,遠小於快SQL的結果集411628,為什麼慢SQL結果集小,邏輯讀反而很大呢?
難道是慢的SQL執行計劃選錯了,導致雖然結果集小,但是cost很高?
分別生成快、慢兩個SQL執行計劃:
慢SQL執行計劃如下:
Elapsed: 00:00:01.98 Execution Plan ---------------------------------------------------------- ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 37 | 21904 | 1424 (1)| | 1 | COUNT STOPKEY | | | | | | 2 | VIEW | | 37 | 21904 | 1424 (1)| | 3 | TABLE ACCESS BY INDEX ROWID| CJCTABXXXX | 37 | 8658 | 1424 (1)| | 4 | INDEX RANGE SCAN | ICJCTABXXXX_4 | 1757 | | 49 (0)| ----------------------------------------------------------------------------------- Note ----- - 'PLAN_TABLE' is old version Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 682865 consistent gets 0 physical reads 0 redo size 6636 bytes sent via SQL*Net to client 542 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 40 rows processed
快SQL執行計劃如下:
Execution Plan ---------------------------------------------------------- ----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 40 | 23680 | 310 (0)| | 1 | COUNT STOPKEY | | | | | | 2 | VIEW | | 40 | 23680 | 310 (0)| | 3 | TABLE ACCESS BY INDEX ROWID| CJCTABXXXX | 40 | 9360 | 310 (0)| | 4 | INDEX RANGE SCAN | ICJCTABXXXX_4 | 1757 | | 13 (0)| ----------------------------------------------------------------------------------- Note ----- - 'PLAN_TABLE' is old version Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 16850 consistent gets 0 physical reads 0 redo size 5866 bytes sent via SQL*Net to client 542 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 40 rows processed
可以看到執行計劃也完全一樣,都是走的ICJCTABXXXX_4索引範圍掃描,
慢的SQL邏輯讀consistent gets(682865)遠高於快的SQL邏輯讀consistent gets(16850)。
疑惑2?
那麼為什麼會出現執行計劃相同,結果集小的邏輯讀反而更大呢?
問題原因:
讓我們在認真看下快慢兩條SQL:
慢SQL:
--電信1.6-1.8秒 select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '2' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime) where rownum <= 40;
快SQL:
--聯通0.1-0.2秒 select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from (select msgserial, objaddr, endtime, retrytimes, srvtype, msgcont, report from CJCTABXXXX where msgstat = '0' and srcaddr = '11111' and xxxxxno = '1' and lastsndtime < to_char(sysdate, 'yyyymmddHH24MISS') order by msglevel, rpttime) where rownum <= 40;
在不考慮xxxxxno條件時,兩個SQL文字是完全一樣的,分別是對msglevel, rpttime排序後取前40條記錄。
那麼出現執行計劃相同,結果集小的邏輯讀反而更大的原因很有可能是因為:
1.SQL並沒有完全執行完order by排序完、回表完然後才去執行rownum<=40操作。
而是邊對部分排序和回表邊取出部分rownum<=40的值。
2.檢查order by msglevel, rpttime排序的兩個列都包含在同一個索引裡,
也就是這兩列排序操作不需要訪問資料塊,只需範圍索引塊,
然後回表返回其他列的值,同時邊回表,邊返回部分rownum <= 40的值。
3.那麼為什麼xxxxxno過濾性差,結果集多的邏輯讀反而少了,這是因為結果集越大,越容易找到前40條符合條件的值。
例如:
有一個大紙箱,裡面混合裝了100個球,其中紅色球80個,籃色球10個,粉色球10個,
請問在紙箱裡分別取出10個紅色球、10個籃色球、10個粉色球,哪個速度更快呢?
顯然是取出10個紅色球速度更快,因為紅色球數量最多,更容易找到10個紅色球。
本次案例也是類似的道理,因為xxxxxno條件過濾性好的結果集小,想取出前40個值時,需要掃描更多的塊,索引邏輯讀更高,速度更慢。
解決方案:
可以考慮調整組合索引,將xxxxxno列加入到組合索引中,具體方案還需要充分測試後在使用。
#####chenjuchao 2021-08-15 21:05#####
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29785807/viewspace-2787034/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 某行系統SQL優化案例(一)OracleSQL優化
- Oracle某行系統SQL優化案例(二)OracleSQL優化
- Oracle某行系統SQL優化案例(三)OracleSQL優化
- Oracle某行系統SQL優化(案例五)OracleSQL優化
- Oracle某X系統SQL最佳化(案例六)OracleSQL
- Oracle SQL*Loader使用案例(四)OracleSQL
- ORACLE SQL效能最佳化系列 (四) (轉)OracleSQL
- Oracle效能優化-SQL優化(案例四)Oracle優化SQL
- DM 傳統行業SQL最佳化案例行業SQL
- Oracle SQL 'or' 的最佳化,最近的案例一則。OracleSQL
- 使用SQL Profile進行SQL最佳化案例SQL
- SQL最佳化案例-union代替or(九)SQL
- 生產系統pl/sql調優案例SQL
- OB案例、金融行業核心系統跑批SQL最佳化行業SQL
- 一次系統延遲性最佳化案例
- Sql 巢狀迴圈最佳化案例SQL巢狀
- SQL最佳化案例-使用with as最佳化Subquery Unnesting(七)SQL
- Oracle SQL效能最佳化OracleSQL
- Oracle sql 效能最佳化OracleSQL
- Oracle "腦殘" CBO 最佳化案例Oracle
- oracle 系統搬遷案例(zw3)Oracle
- Oracle SQL的最佳化[轉]OracleSQL
- Oracle SQL最佳化總結OracleSQL
- Oracle SQL Like 的最佳化OracleSQL
- oracle一次卡頓案例(四)Oracle
- Oracle效能最佳化之SQL最佳化(轉)OracleSQL
- SQL最佳化案例-自定義函式索引(五)SQL函式索引
- SQL最佳化案例-正確的使用索引(二)SQL索引
- SQL最佳化案例-單表分頁語句的最佳化(八)SQL
- SQL優化案例-定位系統中大量的rollback(十八)SQL優化
- SQL最佳化案例-從執行計劃定位SQL問題(三)SQL
- 某行XX系統DB2資料庫遷移實施方案DB2資料庫
- 資料庫最佳化案例—某市中心醫院HIS系統資料庫
- Oracle診斷案例-Sql_traceOracleSQL
- Oracle SQL*Loader使用案例(一)OracleSQL
- Oracle SQL*Loader使用案例(二)OracleSQL
- Oracle SQL*Loader使用案例(三)OracleSQL
- Oracle SQL效能最佳化常用方法OracleSQL