此脚本不依赖统计信息。
当执行计划中出现了 INDEX SKIP SCAN,通常说明需要额外添加一个索引。以下脚本抓出走了 INDEX SKIP SCAN 的 SQL。
select c.sql_text, c.sql_id, b.object_name, d.mbfrom v$sql_plan b,v$sql c,(select owner, segment_name, sum(bytes / 1024 / 1024) mbfrom dba_segmentsgroup by owner, segment_name) dwhere b.sql_id = c.sql_idand b.child_number = c.child_numberand b.object_owner = 'SCOTT'and b.operation = 'INDEX'and b.options = 'SKIP SCAN'and b.object_owner = d.ownerand b.object_name = d.segment_nameorder by 4 desc;
在 Scott 账户中创建如下测试表。
create table t_skip as select * from dba_objects;
Table created.
在 owner 字段上创建一个索引。
create index idx_owner_id on t_skip(owner,object_id);
Index created.
对表收集统计信息。
BEGINDBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',tabname => 'T_SKIP',estimate_percent => 100,method_opt => 'for all columns size skewonly',no_invalidate => FALSE,degree => 1,cascade => TRUE);END;
PL/SQL procedure successfully completed.
执行如下 SQL 并且查看执行计划。
select * from t_skip where object_id < 100;
98 rows selected.Execution Plan----------------------------------------------------------Plan hash value: 979686564-------------------------------------------------------------------------------------| Id |Operation |Name |Rows| Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------------| 0 |SELECT STATEMENT | | 91| 8827 | 95 (0)| 00:00:02 || 1 | TABLE ACCESS BY INDEX ROWID|T_SKIP | 91| 8827 | 95 (0)| 00:00:02 ||* 2 | INDEX SKIP SCAN |IDX_OWNER_ID| 91| | 92 (0)| 00:00:02 |-------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------2 - access("OBJECT_ID"<100)filter("OBJECT_ID"<100)
通过脚本抓出走了 INDEX SKIP SCAN 的 SQL。
select c.sql_text, c.sql_id, b.object_name, d.mbfrom v$sql_plan b,v$sql c,(select owner, segment_name, sum(bytes / 1024 / 1024) mbfrom dba_segmentsgroup by owner, segment_name) dwhere b.sql_id = c.sql_idand b.child_number = c.child_numberand b.object_owner = 'SCOTT'and b.operation = 'INDEX'and b.options = 'SKIP SCAN'and b.object_owner = d.ownerand b.object_name = d.segment_nameorder by 4 desc;
SQL_TEXT SQL_ID OBJECT_NAME MB------------------------------------------ --------------- --------------- ----------select * from t_skip where object_id < 100 0837hu8zxha2y IDX_OWNER_ID 2
