暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 19C 索引范围扫描

原创 Asher.HU 2021-02-04
1288


一个索引范围扫描是值的有序扫描

扫描中的范围可以是有界的,也可以是无界的。优化器通常为具有高选择性的查询选择范围扫描

默认情况下,数据库以升序存储索引,并以相同顺序对其进行扫描。例如,与所述谓词的查询department_id >= 20使用范围扫描返回行排序由索引关键字203040,等。如果多个索引条目具有相同的键,则数据库按rowid升序返回它们,因此0,AAAPvCAAFAAAAFaAAa后跟0,AAAPvCAAFAAAAFaAAg,依此类推。

一个索引范围扫描降是相同的索引范围扫描不同的是在降序数据库返回的行。通常,当按降序对数据进行排序时,或者当查找小于指定值的值时,数据库将使用降序扫描。


8.3.3.1当优化器考虑索引范围扫描时

对于索引范围扫描,索引键必须有多个值。

具体来说,优化器在以下情况下考虑索引范围扫描:

  • 在条件中指定索引的一个或多个前导列。

     条件指定一个或多个表达式和逻辑(布尔)运算符的组合,并返回的值TRUEFALSEUNKNOWN条件的示例包括:

    • department_id = :id
    • department_id < :id
    • department_id > :id
    • AND 索引中前导列的上述条件的组合,例如department_id > :low AND department_id < :hi

      注意:

      为了使优化程序考虑范围扫描,表格的通配符搜索col1 LIKE '%ASD'不得处于领先地位。

  • 索引键可以是0、1或更多值。

小费:

如果需要排序的数据,请使用该ORDER BY子句,并且不要依赖索引。如果索引可以满足ORDER BY子句,则优化器使用此选项,从而避免排序。

当索引可以满足ORDER BY DESCENDING子句时,优化器认为索引范围扫描会下降

如果优化器选择全表扫描或其他索引,则可能需要提示来强制执行此访问路径。提示指示使用特定的索引优化 INDEX(tbl_alias ix_name)INDEX_DESC(tbl_alias ix_name)

也可以看看:

Oracle Database SQL语言参考以了解有关INDEXINDEX_DESC提示的 更多信息


8.3.3.2索引范围扫描如何工作

在索引范围扫描期间,Oracle数据库从根目录转到分支目录。

通常,扫描算法如下:

  1. 读取根块。
  2. 读取分支块。
  3. 交替执行以下步骤,直到检索到所有数据:
    1. 读取一个叶子块以获得一个rowid。
    2. 读取表块以检索行。

    注意:

    在某些情况下,索引扫描会读取一组索引块,对行标识进行排序,然后读取一组表块。

因此,要扫描索引,数据库将在各个叶块之间向后或向前移动。例如,对ID在20到40之间的扫描将找到第一个叶子块,该叶子块的最低键值为20或更大。扫描通过叶节点的链接列表进行水平扫描,直到找到大于40的值,然后停止。

下图说明了使用升序进行的索引范围扫描。一条语句请求列中具有非唯一索引employees记录在此示例中,存在2个部门索引条目 20department_id20

图8-5索引范围扫描



8.3.3.3索引范围扫描:示例

本示例employees使用索引范围扫描表中检索一组值

以下语句查询部门20中薪水大于的员工的记录1000

SELECT * 
FROM   employees 
WHERE  department_id = 20
AND    salary > 1000;

前面的查询具有低基数(返回几行),因此该查询使用department_id上的索引数据库扫描索引,从employees表中获取记录,然后将salary > 1000过滤器应用于这些获取的记录以生成结果。

SQL_ID  brt5abvbxw9tq, child number 0
-------------------------------------
SELECT * FROM   employees WHERE  department_id = 20 AND    salary > 1000
 
Plan hash value: 2799965532
 
-------------------------------------------------------------------------------------------
|Id | Operation                           | Name             |Rows|Bytes|Cost(%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT                    |                  |    |     | 2 (100)|        |
|*1 |  TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES        |  2 | 138 | 2   (0)|00:00:01|
|*2 |   INDEX RANGE SCAN                  | EMP_DEPARTMENT_IX|  2 |     | 1   (0)|00:00:01|
-------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("SALARY">1000)
   2 - access("DEPARTMENT_ID"=20)


8.3.3.4索引范围扫描降序:示例

本示例使用索引以employees排序顺序表中检索行

以下语句20以降序查询部门员工的记录

SELECT *
FROM   employees
WHERE  department_id < 20
ORDER BY department_id DESC;

该先前查询的基数较低,因此该查询使用department_id上的索引

SQL_ID  8182ndfj1ttj6, child number 0
-------------------------------------
SELECT * FROM   employees WHERE  department_id < 20 ORDER BY department_id DESC
 
Plan hash value: 1681890450
--------------------------------------------------------------------------------
|Id| Operation                    | Name           |Rows|Bytes|Cost(%CPU)|Time |
--------------------------------------------------------------------------------
| 0| SELECT STATEMENT             |                   |  |   | 2 (100)|        |
| 1|  TABLE ACCESS BY INDEX ROWID | EMPLOYEES         | 2|138| 2   (0)|00:00:01|
|*2|   INDEX RANGE SCAN DESCENDING| EMP_DEPARTMENT_IX | 2|   | 1   (0)|00:00:01|
--------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("DEPARTMENT_ID"<20)

数据库查找包含最大键值20或小于此值的第一个索引叶块然后,扫描通过叶节点的链接列表向左水平进行。数据库从每个索引条目中获取行ID,然后检索该行ID指定的行。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论