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

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

一条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. 【第五空间智能安全大赛】hate_php WriteUp

    环境:https://www.ctfhub.com/#/challenge 打开题目可以看到源码: 阅读源码发现过滤掉了f l a g . p h / ; " ' ` | [ ] _ =这些 ...

  2. 小程序报错 parameter.content should be String instead of Undefined;

    自己遇到了两种情况会导致这个问题 1.参数名写错未定义,然后赋值的时候值为undefined 2.服务端返回的值错误,返回的值为空,导致赋值时报错 解决方法: 1.检查参数名,如不是全局变量的应在da ...

  3. scala 数据结构(三):元组Tuple

    1 元组Tuple-元组的基本使用 基本介绍 元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据. 说的简单点,就是将多个无关的数据封装为一个整体,称为元组, 最多的特点灵活,对数据没有过多 ...

  4. Linux05 /nginx

    Linux05 /nginx 目录 Linux05 /nginx 1. nginx安装.配置 2. nginx的多虚拟主机功能 3. nginx的访问日志功能,404页面功能 4. nginx的反向代 ...

  5. Django之自带分页模块Pagination

    Django提供了一些类来帮助您管理分页数据 - 即分布在多个页面上的数据,使用“上一页/下一页”链接.这些课程都在django/core/paginator.py. Example¶ 给Pagina ...

  6. Knn和K-means

    先开个标题,以后慢慢填充. k近邻算法(knn)属于监督学习 一. 三个关键点:1.k的取值,当k值较小时,选取点较少,相当于会有在较小的范围内进行学习预测,学习误差会减小,但是估计误差会增大,因为训 ...

  7. unity第一人称如何设置

    关系图 红色菱形:脚本 白色矩形:组件 移动代码 //移动代码 public CharacterController controller;//角色控制器 public float speed = 1 ...

  8. 为什么阿里、头条、美团这些互联网大厂都在用Spring Boot?

    前言 自 2014 年发布至今,Spring Boot 的搜索指数 一路飙升.没错 Spring Boot 越来越火了,作为一名行走一线的 Java 程序员,你可能在各个方面感受到了 Spring B ...

  9. STL Queue(队列)学习笔记 + 洛谷 P1540 机器翻译

    队(Queue) 队简单来说就是一个先进先出的“栈”,但是不同于标准“栈”的先进后出. 基本操作: push(x) 将x压入队列的末端 pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回 ...

  10. jmeter零散知识点