背景:
某表忽然出現查詢非常緩慢的情況,cost 100+ 秒以上;嚴重影響生產。
原SQL:
explain plan for select * from ( select ID id,RET_NO retNo, FROM_SYS fromSy, TO_SYS toSys, COMMAND_CODE commandCode, COMMAND, STATUS, EXT_CODE, ORIGN_CODE orignCode,error_message errorMessage, RE_F, RET_MSG retMsg from interface_table where ((command_code in('AASSS') and status in('F','E') and (re_f = 'N') and FROM_SYS = 'MEE') or (COMMAND_CODE in('XXXX','XXXX9') and FROM_SYS = 'EXT' and RE_F = 'N') ) and MOD(id, 1) = 0 order by id) where rownum <= 100 ;查看其執行計劃:
SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
Plan hash value: 1871549687 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99 | 382K| 637 (1)| 00:00:08 | |* 1 | COUNT STOPKEY | | | | | | | 2 | VIEW | | 100 | 386K| 637 (1)| 00:00:08 | |* 3 | TABLE ACCESS BY INDEX ROWID| INTERFACE_TABLE | 355 | 55735 | 637 (1)| 00:00:08 | |* 4 | INDEX FULL SCAN | PK_INTERFACE_TABLE | 1439 | | 280 (2)| 00:00:04 | ----------------------------------------------------------------------------------------------------
優化後的SQL:
explain plan for select * from ( select /*+ index(INT_TABLE IX_INT_TABLE_2)*/ ID id,RET_NO retNo, FROM_SYS fromSy, TO_SYS toSys, COMMAND_CODE commandCode, COMMAND, STATUS, EXT_CODE, ORIGN_CODE orignCode,error_message errorMessage, RE_F, RET_MSG retMsg from interface_table where ((command_code in('AASSS') and status in('F','E') and (re_f = 'N') and FROM_SYS = 'MEE') or (COMMAND_CODE in('XXXX','XXXX9') and FROM_SYS = 'EXT' and RE_F = 'N') ) and MOD(id, 1) = 0 order by id) where rownum <= 100 ;查看其執行計劃:
SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
Plan hash value: 3625182869 -------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99 | 382K| 19105 (1)| 00:03:50 | |* 1 | COUNT STOPKEY | | | | | | | 2 | VIEW | | 356 | 1376K| 19105 (1)| 00:03:50 | |* 3 | SORT ORDER BY STOPKEY | | 356 | 55892 | 19105 (1)| 00:03:50 | | 4 | CONCATENATION | | | | | | |* 5 | TABLE ACCESS BY INDEX ROWID| INTERFACE_TABLE | 69 | 10833 | 9552 (1)| 00:01:55 | |* 6 | INDEX RANGE SCAN | IX_INTERFACE_TABLE_2 | 77145 | | 99 (0)| 00:00:02 | |* 7 | TABLE ACCESS BY INDEX ROWID| INTERFACE_TABLE | 287 | 45059 | 9552 (1)| 00:01:55 | |* 8 | INDEX RANGE SCAN | IX_INTERFACE_TABLE_2 | 77145 | | 99 (0)| 00:00:02 | --------------------------------------------------------------------------------------------------------比較:
查看執行計劃,原來是使用 full scan - 當數據量大時非常慢;優化後oracle優先走range scan,hint 的 index 是未處理標識字段的索引,正常情況下這個數據集合相對較小--------所以可以達到優化目的。
具體情況具體分析,我們必須要看實際的表存的業務數據,分析其業務關系找到最小業務集合;後者要看懂執行計劃,根據rows, bytes, cost, time 找到最優項目。這個分析順序不能倒置。
問題:為何使用 rownum 後,oracle執行計劃會走full scan?
轉:如何看懂執行計劃:http://jadethao.iteye.com/blog/1613943