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

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

一条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. 1. 初识Jackson -- 世界上最好的JSON库

    要想人前显贵,必须背后受罪.关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis.中 ...

  3. 云小课 | “VPC连接”知多少

    摘要:华为云提供了丰富的网络服务,可满足多种网络互连场景. 同Region的两个VPC怎么连通?” “跨Region的两个VPC又怎么连通?” “VPC内的ECS搭建了一个应用,需要访问Interne ...

  4. web 部署专题(零):web相关概念以及原理

    1.什么是 nginx Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数. 2.正向代理 (1)需 ...

  5. redis(二):Redis 命令

    Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. 语法 Redis 客 ...

  6. Configurate root account

    After having installed Ubuntu OS, you should update config file for root account. The commands are l ...

  7. awesome : vue-awesome 按需引入

    其实挺简单的,被文档带到沟里去了. main.js: 首先讲一下全部引入,很简单. import 'vue-awesome/icons' import Icon from 'vue-awesome/c ...

  8. 题解 洛谷 P5331 【[SNOI2019]通信】

    考虑用费用流解决本题. 每个哨站看作一个点,并将其拆为两个点,建图方式为: \(S \longrightarrow x_i\) 容量为\(1\),费用为\(0\) \(x_i \longrightar ...

  9. DPDK之什么是imissed、ierrors、rx_nombuf

    DPDK之什么是imissed.ierrors.rx_nombuf 在采用DPDK进行网络抓包时常常会通过rte_eth_stats_get函数获取当前网卡的丢包状态,首先看一下该函数的声明: // ...

  10. Crossword Answers -------行与列按序输出

    题目链接:https://vjudge.net/problem/UVA-232#author=0 题意:关键句:The de nitions correspond to the rectangular ...