关于ORACLE索引的几种扫描方式
------------恢复内容开始------------
------------恢复内容开始------------
一条sql执行的效率因执行计划的差异而影响,经常说这条sql走索引了,那条sql 全表扫了。索引是怎么走的呢,说说我了解到的几种索引走的方式。
索引的几种扫描方式
1.Index Unique Scans 索引唯一扫描
2.Index Range Scans 索引范围扫描
3.Index Full Scans 索引全扫描
4.Index Fast Full Scans 索引快速全扫
5.Index Skip Scans 索引跳跃扫描
6.Index Join Scans 索引关联扫描
1.Index Unique Scans 索引唯一扫描(要求高,效率最好)
索引唯一扫描需要一个相等谓词。具体来说,仅当查询谓词使用等号运算符引用唯一索引键中的所有列时,数据库才执行唯一扫描.
PS: 要唯一索引中才有可能触发唯一索引扫描。主键或唯一约束(如果索引非唯一索引)也是无法触发的。
扫描按顺序搜索索引以查找指定的键。索引唯一扫描一旦找到第一条记录就停止处理,因为不可能有第二条记录。数据库从索引条目中获取行标识,然后检索该行标识所指定的行。
例子:
CREATE TABLE "SCOTT"."DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" VARCHAR2(14),
"LOC" VARCHAR2(13),
CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
00:46:24 SQL> select * from scott.dept where DEPTNO=1;
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 2852011669
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
-----非唯一索引,无法使用唯一扫
14:09:55 SQL> CREATE TABLE "SCOTT"."DEPT1"
14:15:18 2 ( "DEPTNO" NUMBER(2,0),
"DNAME" VARCHAR2(14),
14:15:18 3 14:15:18 4 "LOC" VARCHAR2(13));
Table created.
14:15:19 SQL> create index scott.ind_DEPTNO on "SCOTT"."DEPT1"(DEPTNO);
Index created.
14:16:02 SQL> alter table "SCOTT"."DEPT1" add CONSTRAINT "PK_DEPT1" PRIMARY KEY ("DEPTNO");
14:18:17 SQL> select * from scott.dept1 where DEPTNO=1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2017361551
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 0 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT1 | 1 | 30 | 0 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_DEPTNO | 1 | | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
2.Index Range Scans 索引范围扫描
对于索引范围扫描,索引键必须有多个值。
具体来说,优化器在以下情况下考虑索引范围扫描:
在条件中指定索引的一个或多个前导列。
甲条件指定一个或多个表达式和逻辑(布尔)运算符的组合,并返回的值
TRUE
,FALSE
或UNKNOWN
。条件的示例包括:id = :id
id < :id
id > :id
AND
索引中前导列的前述条件的组合,例如id > :low AND id < :hi
范围扫描索引,数据库将在叶块中向后或向前移动。例如,对ID在20到40之间的扫描将找到第一个叶子块,该叶子块的最低键值为20或更大。扫描通过叶节点的链接列表进行水平扫描,直到找到大于40的值,然后停止。
例子:
create table "SCOTT"."DEPT2" as select * from scott.dept;
create index scott.ind_dept2 on table scott.dept2(deptno);
02:36:30 SQL> select * from scott.dept2 where DEPTNO>1;
Execution Plan
----------------------------------------------------------
Plan hash value: 472371293
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 120 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT2 | 4 | 120 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_DEPT2 | 4 | | 1 (0)| 00:00:01 |
---Index Range Scans 如果语句中符合该条件进行范围扫,后面有排序的,将会进行索引范围降序扫描。
INDEX RANGE SCAN DESCENDING
例子:
03:04:16 SQL> select * from scott.dept2 where DEPTNO>1 order by 1 desc;
Execution Plan
----------------------------------------------------------
Plan hash value: 2624219629
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 120 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | DEPT2 | 4 | 120 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN DESCENDING| IND_DEPT2 | 4 | | 1 (0)| 00:00:01 |
3.Index Full Scans 索引全扫描
索引全扫描可以消除单独的排序操作,因为索引中的数据是按索引键排序的。单块IO扫描
优化器会在各种情况下考虑对索引进行全面扫描。
这些情况包括:
谓词引用索引中的列。该列不必是前导列。
未指定谓词,但满足以下所有条件:
表和查询中的所有列都在索引中。
至少一个索引列不为null。
查询包括一个
ORDER BY
在索引上的不可为空的列。
03:29:19 SQL> select DEPTNO,DNAME from scott.dept order by DEPTNO; --主键列,不可为空
Execution Plan
----------------------------------------------------------
Plan hash value: 3103054919
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 52 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 2 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------
4.Index Fast Full Scans 索引快速全扫
索引快速全扫描读取未排序的顺序与索引块,该扫描不使用索引来探测表,而是读取索引而不是表,本质上是将索引本身用作表。
当查询仅访问索引中的属性时,优化器将考虑此扫描。数据库使用多块I / O读取根块以及所有叶块和分支块。数据库将忽略分支块和根块,并读取叶块上的索引条目。
04:53:59 SQL> select /*+ index_ffs(dept4 IND_DEP4) */ count(DEPTNO) from scott.dept4 ;
Execution Plan
----------------------------------------------------------
Plan hash value: 1367395807
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| IND_DEP4 | 1 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
5.Index Skip Scans 索引跳跃扫描
索引跳跃扫描时发生复合索引的初始列是“跳过”或在查询未指定。
通常,跳过扫描索引块比扫描表块快,并且比执行全索引扫描快。
当满足以下条件时,优化器将考虑跳过扫描:
在查询谓词中未指定复合索引的前导列。
例如,查询谓词未引用该DEPTNO列,并且复合索引键为
(DEPTNO,DNAME)
。复合索引的前导列中很少有不同的值,但是索引的非前导键中却存在许多不同的值。
例如,如果组合索引键为
(DEPTNO,DNAME)
,则该DEPTNO列只有两个不同的值,但DNAME有数千个。
索引跳过扫描在逻辑上将组合索引拆分为较小的子索引。索引的前几列中不同值的数量确定逻辑子索引的数量。数字越小,优化器必须创建的逻辑子索引越少,扫描变得越有效。扫描将分别读取每个逻辑索引,并在不超前的列上“跳过”不满足过滤条件的索引块。
DBMS_METADATA.GET_DDL(UPPER('TABLE'),UPPER('EMPLOYEE'),UPPER('SYS'))
------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE TABLE "SYS"."EMPLOYEE"
( "GENDER" VARCHAR2(1),
"EMPLOYEE_ID" NUMBER
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SYSTEM"
INDEX_NAME INDEX_COL INDEX_TYPE PAR
--------------------------------------------- ------------------------------ ---------------------- ---
SYS.IDX_EMPLOYEE GENDER,EMPLOYEE_ID NORMAL-NONUNIQUE NO
05:57:11 SQL> set autotrace traceonly
05:57:19 SQL>
05:57:23 SQL> select * from employee where employee_id = 100;
Execution Plan
----------------------------------------------------------
Plan hash value: 461756150
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 3 (0)| 00:00:01 |
|* 1 | INDEX SKIP SCAN | IDX_EMPLOYEE | 1 | 4 | 3 (0)| 00:00:01 |
------------------------------------------------------------------
6.Index Join Scans 索引关联扫描
索引联接扫描是多个索引的哈希联接,它们一起返回查询请求的所有列。数据库不需要访问表,因为所有数据都是从索引中检索的。
在以下情况下,优化器将考虑使用索引联接:
多个索引的哈希联接检索查询所请求的所有数据,而无需访问表。
从表中检索行的成本比不从表中检索行而读取索引要高。索引联接通常很昂贵。例如,在扫描两个索引并将它们结合在一起时,选择最有选择性的索引然后探查表的成本通常较低。
也可以使用提示指定索引连接。 INDEX_JOIN(table_name)
在索引联接扫描中,始终避免表访问。例如,在单个表上联接两个索引的过程如下:
扫描第一个索引以检索行标识。
扫描第二个索引以检索行ID。
通过rowid执行哈希联接以获取行。
------------恢复内容结束------------
关于ORACLE索引的几种扫描方式的更多相关文章
- Java连接Oracle数据库的三种连接方式
背景: 这两天在学习Oracle数据库,这里就总结下自己上课所学的知识,同时记录下来,方便整理当天所学下的知识,也同时方便日后自己查询. SQL语句的话,这里我就不多讲了,感觉和其他的数据库(MySQ ...
- oracle 索引的几种方式
一.查询索引的高度 select index_name,blevel,leaf_blocks,num_rows,distinct_keys,clustering_factorfrom user_ind ...
- Oracle表的几种连接方式
1,排序 - - 合并连接(Sort Merge Join, SMJ) 2,嵌套循环(Nested Loops, NL) 3,哈希连接(Hash Join, HJ) Join是一种试图将两个表结合在一 ...
- Oracle中的三种Join 方式
基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...
- SQL语句的执行计划(oracle表的三种链接方式)
SQL语句我们写完之后,就是分析其优化,这就要求我们了解到底数据是怎么存储. 首先我们需要了解,表链接的几种方式 nested loop join sort merge join hash join ...
- Oracle常见的几种登录方式
1.运行SQLPLUS工具 C:\Users\csb>sqlplus(回车) (输入账户)system(回车) (输入密码) (回车) 2.直接进入SQLPLUS命令提示符,无用户的登陆 C:\ ...
- oracle 10g下范围分区扫描的几种方式
oracle 10g下有几种扫描方式,注意最后一种扫描方式,当对分区的列进行计算时,会不走分区.这跟对索引列进行计算会导致无法用索引一样. --扫描单个分区 PARTITION RANGE SING ...
- Oracle索引梳理系列(六)- Oracle索引种类之函数索引
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- Oracle 索引扫描的4种类型
根据索引的类型与where限制条件的不同,有4种类型的Oracle索引扫描: 3,4可归一种 (1) 索引唯一扫描(index uniquescan) (2) 索引范围扫描(index range s ...
随机推荐
- kibana限制用户只具备读图的权限
假设需求 因为业务需要将日志系统收集到的信息进行图表化展示并交付到用户进行业务交流. 解决方案 这个需求看着似乎蛮简单的,如何解决? 1.对需要的数据进行过滤制作图表 2.对用户的权限限制为只读级别, ...
- P2882 Face The Right Way G 题解
题目 Farmer John has arranged his N \((1 ≤ N ≤ 5,000)\) cows in a row and many of them are facing forw ...
- python入门008
目录 一.for循环 作用:for循环是因为在循环取值(即遍历值)时for循环比while循环的使用更为简洁 1.for循环语法: 2.应用案例: 注意:break 与 continue也可以用于fo ...
- 浅析Python垃圾回收机制!
Python垃圾回收机制 目录 Python垃圾回收机制 1. 内存泄露 2. Python什么时候启动垃圾回收机制? 2.1 计数引用 2.2 循环引用 问题:引用计数是0是启动垃圾回收的充要条件吗 ...
- python使用数组实现链表的策略分析
python实现链表数据结构:数组/节点与引用 使用数组策略: 使用数组存储指向其他对象的引用 数组存储空间过度分配 数组填满后,分配一个更大的数组,将旧数组的内容复制到新数组中 class Arra ...
- python 追踪函数调用
from flask import Flask import traceback app = Flask(__name__) @app.route('/') def hello_world(): tr ...
- Python Ethical Hacking - VULNERABILITY SCANNER(1)
HTTP REQUESTS BASIC INFORMATION FLOW The user clicks on a link. HTML website generates a request(cli ...
- 集训作业 洛谷P1017 进制转换
这个题的题目真的太恶心了. 重点是他的题目描述和他的目标没啥关系. 和最终目的有关系的只有这么一句话:”输出此负进制数及其基数,若此基数超过10,则参照16进制的方法处理.“ 我们通过看这句话可以发现 ...
- 来了,来了,你们要的Nginx教程来了
一 Nginx简介 1.1 什么是Nginx Nginx是一个高性能的http和反向代理服务器,其特点是占用内存小,并发能力强.Nginx专为性能优化而开发,性能是其最重要的考量,能经受高负载的考验, ...
- TeamViewer如何绑定谷歌二次验证码/谷歌身份验证?
1.下载TeamViewer,找到谷歌二次验证界面 下载.注册TeamViewer后,点击右上角账户名-“编辑配置文件” [常规]-“双重验证”,点“启用” 进入[激活双重验证]界面,点“启动激活 ...