index fast full scan VS. index skip scan
index fast full scan VS. index skip scan
SELECT count(*) FROM TNOTNDB.sysindexes WHERE id = tnotndb.object_id('TNOTNDB..tCustomerUser') AND name = 'idx_tCustomerUser'
这样一个语句(业务逻辑很土鳖,我就不评论了),在其中一个环境中执行需要4分半,计划如下:
11:32:16 SQL> /
Elapsed: 00:04:30.60
Execution Plan
----------------------------------------------------------
Plan hash value: 2154106592
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 127 | 49 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 127 | | |
|* 2 | FILTER | | | | | |
| 3 | NESTED LOOPS | | 1 | 127 | 49 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 1 | 123 | 48 (0)| 00:00:01 |
| 5 | NESTED LOOPS | | 1 | 119 | 47 (0)| 00:00:01 |
| 6 | NESTED LOOPS OUTER | | 1 | 115 | 46 (0)| 00:00:01 |
| 7 | NESTED LOOPS OUTER | | 1 | 107 | 45 (0)| 00:00:01 |
| 8 | NESTED LOOPS OUTER | | 1 | 96 | 44 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 93 | 43 (0)| 00:00:01 |
| 10 | NESTED LOOPS | | 1 | 62 | 41 (0)| 00:00:01 |
|* 11 | INDEX FAST FULL SCAN | I_OBJ2 | 1 | 31 | 40 (0)| 00:00:01 |
|* 12 | TABLE ACCESS CLUSTER | IND$ | 2 | 62 | 1 (0)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | I_OBJ# | 1 | | 0 (0)| 00:00:01 |
|* 14 | TABLE ACCESS BY INDEX ROWID| OBJ$ | 1 | 31 | 2 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | I_OBJ1 | 1 | | 1 (0)| 00:00:01 |
| 16 | TABLE ACCESS CLUSTER | TS$ | 1 | 3 | 1 (0)| 00:00:01 |
|* 17 | INDEX UNIQUE SCAN | I_TS# | 1 | | 0 (0)| 00:00:01 |
| 18 | TABLE ACCESS CLUSTER | SEG$ | 2 | 22 | 1 (0)| 00:00:01 |
|* 19 | INDEX UNIQUE SCAN | I_FILE#_BLOCK# | 1 | | 0 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | I_OBJ1 | 1 | 8 | 1 (0)| 00:00:01 |
|* 21 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
|* 22 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
|* 23 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
| 24 | NESTED LOOPS | | 2 | 42 | 2 (0)| 00:00:01 |
|* 25 | INDEX RANGE SCAN | I_OBJAUTH1 | 1 | 8 | 2 (0)| 00:00:01 |
|* 26 | FIXED TABLE FULL | X$KZSRO | 2 | 26 | 0 (0)| 00:00:01 |
|* 27 | FIXED TABLE FULL | X$KZSPR | 1 | 26 | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("IO"."OWNER#"=USERENV('SCHEMAID') OR EXISTS (SELECT 0 FROM "SYS"."OBJAUTH$"
"OBJAUTH$",SYS."X$KZSRO" "X$KZSRO" WHERE "GRANTEE#"="KZSROROL" AND "OBJ#"=:B1) OR EXISTS
(SELECT 0 FROM SYS."X$KZSPR" "X$KZSPR" WHERE "INST_ID"=USERENV('INSTANCE') AND
((-"KZSPRPRV")=(-45) OR (-"KZSPRPRV")=(-47) OR (-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR
(-"KZSPRPRV")=(-50))))
11 - filter("IO"."TYPE#"=2 AND "IO"."NAME"="TNOTNDB"."OBJECT_ID"('TNOTNDB..tCustomerUser'))
12 - filter(("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
"I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9) AND BITAND("I"."FLAGS",4096)=0)
13 - access("I"."BO#"="IO"."OBJ#")
14 - filter("O"."NAME"='idx_tCustomerUser' AND BITAND("O"."FLAGS",128)=0)
15 - access("O"."OBJ#"="I"."OBJ#")
17 - access("I"."TS#"="TS"."TS#"(+))
19 - access("I"."TS#"="S"."TS#"(+) AND "I"."FILE#"="S"."FILE#"(+) AND
"I"."BLOCK#"="S"."BLOCK#"(+))
20 - access("I"."INDMETHOD#"="ITO"."OBJ#"(+))
21 - access("IO"."OWNER#"="IU"."USER#")
22 - access("ITO"."OWNER#"="ITU"."USER#"(+))
23 - access("U"."USER#"="O"."OWNER#")
25 - access("OBJ#"=:B1)
26 - filter("GRANTEE#"="KZSROROL")
27 - filter("INST_ID"=USERENV('INSTANCE') AND ((-"KZSPRPRV")=(-45) OR (-"KZSPRPRV")=(-47) OR
(-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR (-"KZSPRPRV")=(-50)))
Statistics
----------------------------------------------------------
13144 recursive calls
0 db block gets
5651574 consistent gets
0 physical reads
0 redo size
341 bytes sent via SQL*Net to client
364 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
11:37:28 SQL>
统计sysindexes如下:
11:52:28 SQL> set autotrace traceonly
11:52:57 SQL> select count(*) from sysindexes
11:55:08 2 /
Elapsed: 00:00:00.18
Execution Plan
----------------------------------------------------------
Plan hash value: 996355938
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 87 | 224 (3)| 00:00:03 |
| 1 | SORT AGGREGATE | | 1 | 87 | | |
|* 2 | FILTER | | | | | |
|* 3 | HASH JOIN RIGHT OUTER | | 3100 | 263K| 224 (3)| 00:00:03 |
| 4 | TABLE ACCESS FULL | SEG$ | 4174 | 45914 | 35 (0)| 00:00:01 |
|* 5 | HASH JOIN RIGHT OUTER | | 1763 | 130K| 188 (3)| 00:00:03 |
| 6 | INDEX FULL SCAN | I_USER2 | 47 | 188 | 1 (0)| 00:00:01 |
|* 7 | HASH JOIN OUTER | | 1763 | 123K| 186 (2)| 00:00:03 |
|* 8 | HASH JOIN | | 1763 | 110K| 172 (2)| 00:00:03 |
| 9 | INDEX FULL SCAN | I_USER2 | 47 | 188 | 1 (0)| 00:00:01 |
|* 10 | HASH JOIN | | 1763 | 103K| 170 (2)| 00:00:03 |
|* 11 | HASH JOIN RIGHT OUTER | | 1763 | 86387 | 118 (1)| 00:00:02 |
| 12 | TABLE ACCESS FULL | TS$ | 5 | 15 | 3 (0)| 00:00:01 |
| 13 | NESTED LOOPS | | 1763 | 81098 | 115 (1)| 00:00:02 |
|* 14 | HASH JOIN | | 1353 | 20295 | 16 (7)| 00:00:01 |
| 15 | INDEX FULL SCAN | I_USER2 | 47 | 188 | 1 (0)| 00:00:01 |
|* 16 | INDEX FAST FULL SCAN| I_OBJ1 | 1353 | 14883 | 14 (0)| 00:00:01 |
|* 17 | TABLE ACCESS CLUSTER | IND$ | 1 | 31 | 1 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | I_OBJ# | 1 | | 0 (0)| 00:00:01 |
|* 19 | TABLE ACCESS FULL | OBJ$ | 15449 | 165K| 52 (2)| 00:00:01 |
| 20 | INDEX FAST FULL SCAN | I_OBJ1 | 15449 | 120K| 14 (0)| 00:00:01 |
| 21 | NESTED LOOPS | | 2 | 42 | 2 (0)| 00:00:01 |
|* 22 | INDEX RANGE SCAN | I_OBJAUTH1 | 1 | 8 | 2 (0)| 00:00:01 |
|* 23 | FIXED TABLE FULL | X$KZSRO | 2 | 26 | 0 (0)| 00:00:01 |
|* 24 | FIXED TABLE FULL | X$KZSPR | 1 | 26 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("IO"."OWNER#"=USERENV('SCHEMAID') OR EXISTS (SELECT 0 FROM
"SYS"."OBJAUTH$" "OBJAUTH$",SYS."X$KZSRO" "X$KZSRO" WHERE "GRANTEE#"="KZSROROL" AND
"OBJ#"=:B1) OR EXISTS (SELECT 0 FROM SYS."X$KZSPR" "X$KZSPR" WHERE
"INST_ID"=USERENV('INSTANCE') AND ((-"KZSPRPRV")=(-45) OR (-"KZSPRPRV")=(-47) OR
(-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR (-"KZSPRPRV")=(-50))))
3 - access("I"."FILE#"="S"."FILE#"(+) AND "I"."BLOCK#"="S"."BLOCK#"(+) AND
"I"."TS#"="S"."TS#"(+))
5 - access("ITO"."OWNER#"="ITU"."USER#"(+))
7 - access("I"."INDMETHOD#"="ITO"."OBJ#"(+))
8 - access("U"."USER#"="O"."OWNER#")
10 - access("O"."OBJ#"="I"."OBJ#")
11 - access("I"."TS#"="TS"."TS#"(+))
14 - access("IO"."OWNER#"="IU"."USER#")
16 - filter("IO"."TYPE#"=2)
17 - filter(("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
"I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9) AND BITAND("I"."FLAGS",4096)=0)
18 - access("I"."BO#"="IO"."OBJ#")
19 - filter(BITAND("O"."FLAGS",128)=0)
22 - access("OBJ#"=:B1)
23 - filter("GRANTEE#"="KZSROROL")
24 - filter("INST_ID"=USERENV('INSTANCE') AND ((-"KZSPRPRV")=(-45) OR
(-"KZSPRPRV")=(-47) OR (-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR
(-"KZSPRPRV")=(-50)))
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
28723 consistent gets
0 physical reads
0 redo size
344 bytes sent via SQL*Net to client
364 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
11:55:10 SQL>
但是在另外一个镜像环境上,这个语句是OK的:
11:32:13 SQL> /
Elapsed: 00:00:00.06
Execution Plan
----------------------------------------------------------
Plan hash value: 3331003661
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 125 | 77 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 125 | | |
|* 2 | FILTER | | | | | |
| 3 | NESTED LOOPS | | 1 | 125 | 77 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 1 | 121 | 76 (0)| 00:00:01 |
| 5 | NESTED LOOPS | | 1 | 117 | 75 (0)| 00:00:01 |
| 6 | NESTED LOOPS OUTER | | 1 | 113 | 74 (0)| 00:00:01 |
| 7 | NESTED LOOPS OUTER | | 1 | 105 | 73 (0)| 00:00:01 |
| 8 | NESTED LOOPS OUTER | | 1 | 94 | 72 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 91 | 71 (0)| 00:00:01 |
| 10 | NESTED LOOPS | | 1 | 61 | 69 (0)| 00:00:01 |
|* 11 | INDEX SKIP SCAN | I_OBJ2 | 1 | 30 | 68 (0)| 00:00:01 |
|* 12 | TABLE ACCESS CLUSTER | IND$ | 1 | 31 | 1 (0)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | I_OBJ# | 1 | | 0 (0)| 00:00:01 |
|* 14 | TABLE ACCESS BY INDEX ROWID| OBJ$ | 1 | 30 | 2 (0)| 00:00:01 |
|* 15 | INDEX RANGE SCAN | I_OBJ1 | 1 | | 1 (0)| 00:00:01 |
| 16 | TABLE ACCESS CLUSTER | TS$ | 1 | 3 | 1 (0)| 00:00:01 |
|* 17 | INDEX UNIQUE SCAN | I_TS# | 1 | | 0 (0)| 00:00:01 |
| 18 | TABLE ACCESS CLUSTER | SEG$ | 1 | 11 | 1 (0)| 00:00:01 |
|* 19 | INDEX UNIQUE SCAN | I_FILE#_BLOCK# | 1 | | 0 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | I_OBJ1 | 1 | 8 | 1 (0)| 00:00:01 |
|* 21 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
|* 22 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
|* 23 | INDEX RANGE SCAN | I_USER2 | 1 | 4 | 1 (0)| 00:00:01 |
| 24 | NESTED LOOPS | | 2 | 42 | 2 (0)| 00:00:01 |
|* 25 | INDEX RANGE SCAN | I_OBJAUTH1 | 1 | 8 | 2 (0)| 00:00:01 |
|* 26 | FIXED TABLE FULL | X$KZSRO | 2 | 26 | 0 (0)| 00:00:01 |
|* 27 | FIXED TABLE FULL | X$KZSPR | 1 | 26 | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("IO"."OWNER#"=USERENV('SCHEMAID') OR EXISTS (SELECT 0 FROM "SYS"."OBJAUTH$"
"OBJAUTH$",SYS."X$KZSRO" "X$KZSRO" WHERE "GRANTEE#"="KZSROROL" AND "OBJ#"=:B1) OR EXISTS
(SELECT 0 FROM SYS."X$KZSPR" "X$KZSPR" WHERE "INST_ID"=USERENV('INSTANCE') AND
((-"KZSPRPRV")=(-45) OR (-"KZSPRPRV")=(-47) OR (-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR
(-"KZSPRPRV")=(-50))))
11 - access("IO"."NAME"="TNOTNDB"."OBJECT_ID"('TNOTNDB..tCustomerUser') AND "IO"."TYPE#"=2)
filter("IO"."TYPE#"=2 AND "IO"."NAME"="TNOTNDB"."OBJECT_ID"('TNOTNDB..tCustomerUser'))
12 - filter(("I"."TYPE#"=1 OR "I"."TYPE#"=2 OR "I"."TYPE#"=3 OR "I"."TYPE#"=4 OR
"I"."TYPE#"=6 OR "I"."TYPE#"=7 OR "I"."TYPE#"=9) AND BITAND("I"."FLAGS",4096)=0)
13 - access("I"."BO#"="IO"."OBJ#")
14 - filter("O"."NAME"='idx_tCustomerUser' AND BITAND("O"."FLAGS",128)=0)
15 - access("O"."OBJ#"="I"."OBJ#")
17 - access("I"."TS#"="TS"."TS#"(+))
19 - access("I"."TS#"="S"."TS#"(+) AND "I"."FILE#"="S"."FILE#"(+) AND
"I"."BLOCK#"="S"."BLOCK#"(+))
20 - access("I"."INDMETHOD#"="ITO"."OBJ#"(+))
21 - access("IO"."OWNER#"="IU"."USER#")
22 - access("ITO"."OWNER#"="ITU"."USER#"(+))
23 - access("U"."USER#"="O"."OWNER#")
25 - access("OBJ#"=:B1)
26 - filter("GRANTEE#"="KZSROROL")
27 - filter("INST_ID"=USERENV('INSTANCE') AND ((-"KZSPRPRV")=(-45) OR (-"KZSPRPRV")=(-47) OR
(-"KZSPRPRV")=(-48) OR (-"KZSPRPRV")=(-49) OR (-"KZSPRPRV")=(-50)))
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
991 consistent gets
0 physical reads
0 redo size
341 bytes sent via SQL*Net to client
364 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
11:32:54 SQL>
区别就是一个使用了index fast full scan另外一个使用了index skip scan(第11步),导致逻辑读差距很大
两个环境都是一样的,Linux Oracle 11.1,CPU 32 颗,内存 64 GB
使用Hint也不管用,我很奇怪Oracle为什么为选择Index Fast Full Scan,这个逻辑读很高,很慢