索引的几种扫描方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxzhaobb/article/details/82704486

1  Full Index Scan

In a full index scan, the database reads the entire index in order. A full index scan is
available if a predicate (WHERE clause) in the SQL statement references a column in the
index, and in some circumstances when no predicate is specified. A full scan can
eliminate sorting because the data is ordered by index key.

-- 创建测试用表

create table employees as select * from hr.employees;
create index idx_1 on employees(department_id,last_name,salary)

SELECT department_id, last_name, salary
FROM employees
WHERE salary > 5000
ORDER BY department_id, last_name;

[email protected]/nocdb>set autotrace traceonly
[email protected]/nocdb>set linesize 120
[email protected]/nocdb>SELECT department_id, last_name, salary
  2  FROM employees
  3  WHERE salary > 5000
  4  ORDER BY department_id, last_name;

已选择 58 行。


执行计划
----------------------------------------------------------
Plan hash value: 3375905911

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |    58 |  2320 |     1   (0)| 00:00:01 |
|*  1 |  INDEX FULL SCAN | IDX_1 |    58 |  2320 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("SALARY">5000)
       filter("SALARY">5000)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)


统计信息
----------------------------------------------------------
          6  recursive calls
          0  db block gets
         13  consistent gets
          0  physical reads
          0  redo size
       2205  bytes sent via SQL*Net to client
        640  bytes received via SQL*Net from client
          5  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         58  rows processed

[email protected]/nocdb>

官方文档上关于上面例子的解释
In this example, the department_id, last_name, and salary are a composite key
in an index. Oracle Database performs a full scan of the index, reading it in sorted
order (ordered by department ID and last name) and filtering on the salary attribute.
In this way, the database scans a set of data smaller than the employees table, which
contains more columns than are included in the query, and avoids sorting the data.

2 Fast Full Index Scan (没测试成功)
官方文档上的解释
A fast full index scan is a full index scan in which the database accesses the data in
the index itself without accessing the table, and the database reads the index blocks in
no particular order.
Fast full index scans are an alternative to a full table scan when both of the following
conditions are met:
• The index must contain all columns needed for the query.
• A row containing all nulls must not appear in the query result set. For this result
to be guaranteed, at least one column in the index must have either:
– A NOT NULL constraint
– A predicate applied to the column that prevents nulls from being considered
in the query result set


drop index idx_1;
create index idx_1 on employees(last_name,salary);

SELECT last_name, salary FROM employees;

3 index range scan
官方文档的解释
An index range scan is an ordered scan of an index in which one or
more leading columns of an index are specified in conditions, and 0,
1, or more values are possible for an index key.
A condition specifies a combination of one or more expressions and logical (Boolean)
operators and returns a value of TRUE, FALSE, or UNKNOWN.
The database commonly uses an index range scan to access selective data. The
selectivity is the percentage of rows in the table that the query selects, with 0 meaning
no rows and 1 meaning all rows. Selectivity is tied to a query predicate, such as WHERE
last_name LIKE 'A%', or a combination of predicates. A predicate becomes more
selective as the value approaches 0 and less selective (or more unselective) as the value
approaches 1.
The database could use a range scan because the last_name column is specified in
the predicate and multiples rowids are possible for each index key. For example, two
employees are named Austin, so two rowids are associated with the key Austin.
An index range scan can be bounded on both sides, as in a query for departments with
IDs between 10 and 40, or bounded on only one side, as in a query for IDs over 40. To
scan the index, the database moves backward or forward through the leaf blocks. For
example, a scan for IDs between 10 and 40 locates the first index leaf block that
contains the lowest key value that is 10 or greater. The scan then proceeds horizontally
through the linked list of leaf nodes until it locates a value greater than 40.

--索引的前导列在where条件中

create index IDX_2 on EMPLOYEES (LAST_NAME, SALARY)

[email protected]/nocdb>SELECT last_name, salary FROM employees where last_name='Bell';


执行计划
----------------------------------------------------------
Plan hash value: 863794418

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    10 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_2 |     1 |    10 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("LAST_NAME"='Bell')


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        624  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

-- 当出现like语句的时候,

[email protected]/nocdb>SELECT last_name, salary FROM employees where last_name like 'B%';

已选择 9 行。


执行计划
----------------------------------------------------------
Plan hash value: 863794418

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     8 |    80 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_2 |     8 |    80 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("LAST_NAME" LIKE 'B%')
       filter("LAST_NAME" LIKE 'B%')


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        785  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          9  rows processed

[email protected]/nocdb>

-- between语句也可以

drop Index idx_2;
create index idx_1 on employees(salary,last_name);
[email protected]/nocdb>SELECT last_name, salary FROM employees where salary between 5000 and 8000;

已选择 25 行。


执行计划
----------------------------------------------------------
Plan hash value: 3428004586

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |    25 |   250 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_1 |    25 |   250 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("SALARY">=5000 AND "SALARY"<=8000)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
       1189  bytes sent via SQL*Net to client
        618  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         25  rows processed

[email protected]/nocdb>

index skip scan

官方的解释
An index skip scan uses logical subindexes of a composite index. The database "skips"
through a single index as if it were searching separate indexes.
Skip scanning is beneficial if there are few distinct values in the leading column of a
composite index and many distinct values in the nonleading key of the index. The
database may choose an index skip scan when the leading column of the composite
index is not specified in a query predicate.

-- 前导列不在where谓词

drop index idx_1;
create index idx_1 on employees(last_name,salary);
select last_name,salary from employees where salary=7300;

[email protected]/nocdb>select last_name,salary from employees where salary=7300;


执行计划
----------------------------------------------------------
Plan hash value: 2005042524

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |    10 |     1   (0)| 00:00:01 |
|*  1 |  INDEX SKIP SCAN | IDX_1 |     1 |    10 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("SALARY"=7300)
       filter("SALARY"=7300)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        625  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

[email protected]/nocdb>

Index Unique Scan
官方的解释
In contrast to an index range scan, an index unique scan must have either 0 or 1 rowid
associated with an index key. The database performs a unique scan when a predicate
references all of the columns in the key of a UNIQUE index using an equality operator.
An index unique scan stops processing as soon as it finds the first record because no
second record is possible

create unique index idx_u_1 on employees(employee_id);
SELECT * FROM employees WHERE employee_id = 5;

[email protected]/nocdb>create unique index idx_u_1 on employees(employee_id);

索引已创建。

[email protected]/nocdb>SELECT * FROM employees WHERE employee_id = 5;

未选定行


执行计划
----------------------------------------------------------
Plan hash value: 3378926966

-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |     1 |    62 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES |     1 |    62 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | IDX_U_1   |     1 |       |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPLOYEE_ID"=5)


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
       1069  bytes sent via SQL*Net to client
        596  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

[email protected]/nocdb>

END

猜你喜欢

转载自blog.csdn.net/xxzhaobb/article/details/82704486