索引范圍掃描(INDEX RANGE SCAN)適用於所有類型的B樹索引,當掃描的對象是唯一性索引時,此時目標SQL的where條件一定是范圍查詢(謂詞條件為 BETWEEN、<、>等);當掃描的對象是非唯一性索引時,對目標SQL的where條件沒有限制(可以是等值查詢,也可以是范圍查詢)。 索引范圍掃描的結果可能會返回多條記錄,其實這就是索引范圍掃描中"范圍"二字的本質含義。
測試一:唯一索引的范圍查詢
SCOTT@PDBORCL> select * from emp where empno>7369; 已選擇 13 行。 執行計划 ---------------------------------------------------------- Plan hash value: 2787773736 ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 13 | 494 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMP | 13 | 494 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | PK_EMP | 13 | | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO">7369) 統計信息 ---------------------------------------------------------- 54 recursive calls 0 db block gets 97 consistent gets 21 physical reads 0 redo size 1607 bytes sent via SQL*Net to client 544 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 8 sorts (memory) 0 sorts (disk) 13 rows processed SCOTT@PDBORCL>
SCOTT@PDBORCL> select * from emp where empno>7369 order by empno desc; (降序排列)
SCOTT@PDBORCL> select * from emp where empno>7369 order by empno desc; 已選擇 13 行。 執行計划 ---------------------------------------------------------- Plan hash value: 2707196548 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 13 | 494 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID | EMP | 13 | 494 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN DESCENDING| PK_EMP | 13 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO">7369) 統計信息 ---------------------------------------------------------- 54 recursive calls 0 db block gets 97 consistent gets 21 physical reads 0 redo size 1607 bytes sent via SQL*Net to client 544 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 8 sorts (memory) 0 sorts (disk) 13 rows processed SCOTT@PDBORCL>
這個執行計划和上面的執行計划有什么區別呢?其中第一個執行計划是索引范圍掃描(INDEX RANGE SCAN),但是第二個執行計划是索引范圍降序掃描(INDEX RANGE SCAN DESCENDING)。由此可以看出對於唯一索引,ORACLE是已經進行了正序排列了。也就是唯一索引在進行排序的時候消耗不是很大的,因為它在保存 的時候就按照升序進行保存的。
測試二:非唯一索引的等值查詢
創建一個測試表EMP_TEMP:
create table emp_temp as select * from emp;
然后在表EMP_TEMP的列EMPNO上創建一個單鍵值非唯一性同名B樹索引IDX_EMP_TEMP:
create index idx_emp_temp on emp_temp(empno);
最后我們再次執行如下SQL:
select * from emp_temp where empno=7369;
執行計划如下:
SCOTT@PDBORCL> create table emp_temp as select * from emp; 表已創建。 SCOTT@PDBORCL> create index idx_emp_temp on emp_temp(empno); 索引已創建。 SCOTT@PDBORCL> select * from emp_temp where empno=7369; 執行計划 ---------------------------------------------------------- Plan hash value: 1638992559 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 38 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMP_TEMP | 1 | 38 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_EMP_TEMP | 1 | | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO"=7369) 統計信息 ---------------------------------------------------------- 46 recursive calls 0 db block gets 76 consistent gets 16 physical reads 0 redo size 1042 bytes sent via SQL*Net to client 544 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processed SCOTT@PDBORCL>
此SQL的執行計划已經從之前的索引唯一性掃描變為現在的索引范圍掃描
測試三:非唯一索引的范圍查詢
同樣是測試二中的表EMP_TEMP
SCOTT@PDBORCL> select * from emp_temp where empno>7369;
執行計划如下:
SCOTT@PDBORCL> select * from emp_temp where empno>7369; 已選擇 13 行。 執行計划 ---------------------------------------------------------- Plan hash value: 1638992559 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 13 | 494 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMP_TEMP | 13 | 494 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | IDX_EMP_TEMP | 13 | | 1 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("EMPNO">7369) 統計信息 ---------------------------------------------------------- 46 recursive calls 0 db block gets 77 consistent gets 15 physical reads 0 redo size 1607 bytes sent via SQL*Net to client 544 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 13 rows processed SCOTT@PDBORCL>



