------------恢复内容开始------------

------------恢复内容开始------------

一条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 索引范围扫描

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

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

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

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

    • 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)

在索引联接扫描中,始终避免表访问。例如,在单个表上联接两个索引的过程如下:

  1. 扫描第一个索引以检索行标识。

  2. 扫描第二个索引以检索行ID。

  3. 通过rowid执行哈希联接以获取行。

------------恢复内容结束------------

关于ORACLE索引的几种扫描方式的更多相关文章

  1. Java连接Oracle数据库的三种连接方式

    背景: 这两天在学习Oracle数据库,这里就总结下自己上课所学的知识,同时记录下来,方便整理当天所学下的知识,也同时方便日后自己查询. SQL语句的话,这里我就不多讲了,感觉和其他的数据库(MySQ ...

  2. oracle 索引的几种方式

    一.查询索引的高度 select index_name,blevel,leaf_blocks,num_rows,distinct_keys,clustering_factorfrom user_ind ...

  3. Oracle表的几种连接方式

    1,排序 - - 合并连接(Sort Merge Join, SMJ) 2,嵌套循环(Nested Loops, NL) 3,哈希连接(Hash Join, HJ) Join是一种试图将两个表结合在一 ...

  4. Oracle中的三种Join 方式

    基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort merge join: 将两个表排序,然后再 ...

  5. SQL语句的执行计划(oracle表的三种链接方式)

    SQL语句我们写完之后,就是分析其优化,这就要求我们了解到底数据是怎么存储. 首先我们需要了解,表链接的几种方式 nested loop join sort merge join hash join ...

  6. Oracle常见的几种登录方式

    1.运行SQLPLUS工具 C:\Users\csb>sqlplus(回车) (输入账户)system(回车) (输入密码) (回车) 2.直接进入SQLPLUS命令提示符,无用户的登陆 C:\ ...

  7. oracle 10g下范围分区扫描的几种方式

    oracle 10g下有几种扫描方式,注意最后一种扫描方式,当对分区的列进行计算时,会不走分区.这跟对索引列进行计算会导致无法用索引一样. --扫描单个分区  PARTITION RANGE SING ...

  8. Oracle索引梳理系列(六)- Oracle索引种类之函数索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  9. Oracle 索引扫描的4种类型

    根据索引的类型与where限制条件的不同,有4种类型的Oracle索引扫描: 3,4可归一种 (1) 索引唯一扫描(index uniquescan) (2) 索引范围扫描(index range s ...

随机推荐

  1. CF833 A The Meaningless Game

    题干 Slastyona and her loyal dog Pushok are playing a meaningless game that is indeed very interesting ...

  2. scrapy框架携带cookie访问淘宝购物车

    我们知道,有的网页必须要登录才能访问其内容.scrapy登录的实现一般就三种方式. 1.在第一次请求中直接携带用户名和密码. 2.必须要访问一次目标地址,服务器返回一些参数,例如验证码,一些特定的加密 ...

  3. wcf服务各种情况下应用

    1.控制台调用 第一步,添加wcf服务 2.写接口,记得要加好契约特性. 3.声明一个类继承wcf服务. 4.ipconfig配置 5.控制台运行 6.运行app.config里面,加上调用的接口方法 ...

  4. [JAVA]字符串常量池String pool

    字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定.不仅如此,还可以使用 String 的 intern() 方法在运行过程中将 ...

  5. kubernetes系列(十四) - 存储之PersistentVolume

    1. PersistentVolume(PV)简介 1.1 为什么需要Persistent Volume(PV) 1.2 PersistentVolume(PV)和Volume的区别 1.3 PV和P ...

  6. FileBeat yml配置文件 -常用参数详解

    #filebeat 5.2.2 #prospector(input)段配置 filebeat.prospectors: #每一个prospectors,起始于一个破折号"-" - ...

  7. 【TokyoWesterns CTF】shrine

    信息: 题目来源:TokyoWesterns CTF 标签:flask.SSTI 解题过程 构建题目环境后,访问主页可以获得程序源码: import flask import os app = fla ...

  8. hihoCoder 1041 国庆出游 最详细的解题报告

    题目来源:国庆出游 解题思路(下面是大神的写的): 把题目中的序列称作S,树称作T.那么对于S中的任意节点x,x的子孙节点如果在S出现的话,那么这个子孙节点的位置是有一定要求的:x的所有子孙节点在S中 ...

  9. 【五学x红小豆xRS】两边三地大联动-句型

    <第五共和国> Tohara LY Sara'm, Sabang Chua Setuk KS Kareh Moh Induree Junchi Chueh? 阁下!和这样的虫豸在一起,怎么 ...

  10. 关于Mint-UI中loadmore组件的兼容性问题

    源代码 遇到的问题 写完了之后数据加载,渲染等等都是没有问题的,但是测试总是提上滑刷新不能用,因为是远程开发,测试提就得改,看代码看文档,看半天看不出来问题,想到了兼容性问题,发现也有人遇到这个坑.安 ...