oracle 基础知识(十四)----索引扫描
(1)索引唯一扫描(index unique scan)
通过唯一索引查找一个数值经常返回单个ROWID。如果该唯一索引有多个列组成(即组合索引),则至少要有组合索引的引导列参与到该查询中,如创建一个索引:create index idx_test on emp(ename, deptno, loc)。则select ename from emp where ename = ‘JACK’ and deptno = ‘DEV’语句可以使用该索引。如果该语句只返回一行,则存取方法称为索引唯一扫描。而select ename from emp where deptno = ‘DEV’语句则不会使用该索引,因为where子句种没有引导列。如果存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)的话,Oracle经常实现唯一性扫描。
为了方便查看设置执行计划为只显示执行计划
- SQL> set autot traceonly exp;
- SQL> select * from scott.emp t where t.empno=10;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 2949544139
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
- |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 38 | 1 (0)| 00:00:01 |
- | 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 38 | 1 (0)| 00:00:01 |
- |* 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - access("T"."EMPNO"=10)
- SQL>
(2)索引范围扫描(index range scan)
使用一个索引存取多行数据,同上面一样,如果索引是组合索引,而且select ename from emp where ename = ‘JACK’ and deptno = ‘DEV’ 语句返回多行数据,虽然该语句还是使用该组合索引进行查询,可此时的存取方法称为索引范围扫描。
在唯一索引上使用索引范围扫描的典型情况下是在谓词(where限制条件)中使用了范围操作符(如>、<、<>、>=、<=、between)
- SQL> select empno,ename from scott.emp where empno > 6666 order by empno;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 169057108
- --------------------------------------------------------------------------------
- ------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
- |
- --------------------------------------------------------------------------------
- ------
- | 0 | SELECT STATEMENT | | 14 | 140 | 2 (0)| 00:0
- 0:01 |
- | 1 | TABLE ACCESS BY INDEX ROWID| EMP | 14 | 140 | 2 (0)| 00:0
- 0:01 |
- |* 2 | INDEX RANGE SCAN | PK_EMP | 14 | | 1 (0)| 00:0
- 0:01 |
- --------------------------------------------------------------------------------
- ------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - access("EMPNO">6666)
在非唯一索引上,谓词可能返回多行数据,所以在非唯一索引上都使用索引范围扫描。
使用index rang scan的3种情况:
(a) 在唯一索引列上使用了range操作符(> < <> >= <= between)。
(b) 在组合索引上,只使用部分列进行查询,导致查询出多行。
(c) 对非唯一索引列上进行的任何查询。
(3)索引全扫描(index full scan)
与全表扫描对应,也有相应的全Oracle索引扫描。在某些情况下,可能进行全Oracle索引扫描而不是范围扫描,需要注意的是全Oracle索引扫描只在CBO模式下才有效。 CBO根据统计数值得知进行全Oracle索引扫描比进行全表扫描更有效时,才进行全Oracle索引扫描,而且此时查询出的数据都必须从索引中可以直接得到。
- SQL> create index big_emp on scott.emp(empno,ename); ---创建索引
- Index created.
- SQL> select empno, ename from scott.emp order by empno,ename; 执行计划查看你
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 322359667
- ----------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 14 | 140 | 1 (0)| 00:00:01 |
- | 1 | INDEX FULL SCAN | BIG_EMP | 14 | 140 | 1 (0)| 00:00:01 |
- ----------------------------------------------------------------------------
(4)索引快速扫描(index fast full scan)
扫描索引中的所有的数据块,与 index full scan很类似,但是一个显著的区别就是它不对查询出的数据进行排序,即数据不是以排序顺序被返回。在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。
测试表创建: ---资源来自>>
- create table t as select * from dba_objects where 1=2;
- insert into t select * from dba_objects where object_id is not null;
- 创建一个索引
- create index i_t_object_id on t(object_id);
- select object_id from t;
- set autot trace exp; -- 设置格式
- 查询:select object_id from t;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 1601196873
- --------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 89550 | 1136K| 336 (1)| 00:00:05 |
- | 1 | TABLE ACCESS FULL| T | 89550 | 1136K| 336 (1)| 00:00:05 |
- --------------------------------------------------------------------------
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 这个好像走的是全表呀...由于我们需要查询的列为object_id,因此理论上只需要读取索引就应该可以返回所有数据,而此时为什么是全表扫描呢?这是因为NULL值与索引的特性所决定的。即null值不会被存储到B树索引。因此应该为表 t 的列 object_id 添加 not null 约束。
- alter table t modify(object_id not null); 添加约束
- 再次查看
- SQL> select object_id from t;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 2036340805
- --------------------------------------------------------------------------------
- ------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
- |
- --------------------------------------------------------------------------------
- ------
- | 0 | SELECT STATEMENT | | 89550 | 1136K| 53 (0)| 00:0
- 0:01 |
- | 1 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 89550 | 1136K| 53 (0)| 00:0
- 0:01 |
- --------------------------------------------------------------------------------
- ------
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- INDEX FAST FULL SCAN
- 类似于full table scan,使用该方式当在高速缓存中没有找到所需的索引块时,则根据db_file_multiblock_read_count的值进行多块读操
- 作。对于索引的分支结构只是简单的获取,然后扫描所有的叶结点。其结果是导致索引结构没有访问,获取的数据没有根据索引键的顺序排序。
- INDEX FAST FULL SCAN使用multiblock_read,故产生db file scattered reads 事件
Execution Plan
----------------------------------------------------------
Plan hash value: 431110666
--------------------------------------------------------------------------------
--
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
--
| 0 | SELECT STATEMENT | | 89550 | 1136K| 194 (1)| 00:00:03
|
| 1 | INDEX FULL SCAN | I_T_OBJECT_ID | 89550 | 1136K| 194 (1)| 00:00:03
|
--------------------------------------------------------------------------------
--
Note
-----
- dynamic sampling used for this statement (level=2)
与INDEX FAST FULL SCAN所不同的是,INDEX FULL SCAN会完全按照索引存储的顺序依次访问整个索引树。当访问到叶结点之后,按照双向
链表方式读取相连节点的值。换言之,对于索引上所有的数据是按照有序的方式来读取的。如果索引块没有在高速缓存中被找到时,则需要从数
据文件中单块进行读取。对于需要读取大量数据的全索引扫描而言,这将使其变得低效。INDEX FULL SCAN使用single read,故产生
db file sequential reads事件。新版的Oracle支持db file parallel reads方式。
(5)索引跳跃扫描(INDEX SKIP SCAN)
INDEX SKIP SCAN,发生在多个列建立的复合索引上,如果SQL中谓词条件只包含索引中的部分列,并且这些列不是建立索引时的第一列时,就可能发生INDEX SKIP SCAN。这里SKIP的意思是因为查询条件没有第一列或前面几列,被忽略了。
例子来自于>>>
- SQL> create table employee(gender varchar2(1),employee_id number);
- Table created.
- SQL> alter table employee modify(employee_id not null);
- Table altered.
- SQL> create index idx_employee on employee(gender,employee_id);
- Index created.
- SQL> begin
- for i in 5001..10000 loop
- insert into employee values ('M',i);
- end loop;
- commit;
- end;
- SQL> /
- PL/SQL procedure successfully completed.
- SQL> begin
- for i in 1..5000 loop
- insert into employee values ('F',i);
- end loop;
- commit;
- end;
- SQL> /
- PL/SQL procedure successfully completed.
- SQL> analyze table EMPLOYEE compute statistics for table for all columns for all indexes;
- Table analyzed.
- 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
- |
- --------------------------------------------------------------------------------
- -
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("EMPLOYEE_ID"=100)
- filter("EMPLOYEE_ID"=100)
- SQL>
oracle 基础知识(十四)----索引扫描的更多相关文章
- oracle 基础知识(十二)----索引
一, 索引介绍 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是一个独立于 ...
- oracle 基础知识(十五)----高水位线
一,oracle的逻辑存储管理 ORACLE的逻辑存储管理,分4个粒度:表空间,段,区和块. ## 块 粒度最小的存储单位,现在标准的块大小是8K,ORACLE每一次I/O操作也是按块来操作的,也就是 ...
- Android学习之基础知识十四 — Android特色开发之基于位置的服务
一.基于位置的服务简介 LBS:基于位置的服务.随着移动互联网的兴起,这个技术在最近的几年里十分火爆.其实它本身并不是什么时髦的技术,主要的工作原理就是利用无线电通讯网络或GPS等定位方式来确定出移动 ...
- oracle 基础知识(十)----exp/imp--->>>>>expdp/impdp
一,简介 存活下来的远古级别的导入导出软件exp/imp ,软件多数使用于oracle 9i 之前 到了10g以后基本全面被数据库泵(Data Pump)取代,即expdp/impdp.本文会分别介 ...
- oracle 基础知识(四)常用函数
SQL中的单记录函数 .ASCII 返回与指定的字符对应的十进制数; SQL') zero,ascii(' ') space from dual; A A ZERO SPACE --------- - ...
- 正则表达式、Calendar类、SimpleDateFormat类、Date类、BigDecimal类、BigInteger类、System类、Random类、Math类(Java基础知识十四)
1.正则表达式的概述和简单使用 * A:正则表达式(一个字符串,是规则) * 是指一个用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串.其实就是一种规则.有自己特殊的应用. * B: ...
- Oracle基础 (十四)其他函数
转换函数: TO_DATE:转换为日期 --将字符串转换为日期 SELECT TO_DATE('2014-12-31', 'yyyy-mm-dd') FROM DUAL; SELECT TO_DATE ...
- ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...
- Oracle基础知识汇总一
Oracle基础知识 以下内容为本人的学习笔记,如需要转载,请声明原文链接 https://www.cnblogs.com/lyh1024/p/16720759.html oracle工具: SQ ...
随机推荐
- psimpl_v7_win32_demo
psimpl - generic n-dimensional polyline simplification 通用N维折线简化程序 Author - Elmar de Koning 作者 - Elma ...
- Schwartz kernel theorem施瓦兹核定理
In mathematics, the Schwartz kernel theorem is a foundational result in the theory of generalized fu ...
- git手动解决内容冲突
<span style="font-size:18px;">git checkout -b lab4 origin/lab4 git merge lab3</sp ...
- ArcGIS Engine 中对栅格数据的波段信息统计 (转)
先打开栅格文件所在的工作空间(文件),然后获取其所有的波段,访问每一个波段有时候波段中已经有直方图或统计信息,有时候没有这些信息,可以使用ComputeStatsAndHist()函数对其进行计算(数 ...
- 软件工程实践一 —— java之wc.exe
SoftwareEngineering-wc github项目地址:https://github.com/CuiLam/SoftwareEngineering-wc 项目相关要求 实现一个统计程序 ...
- .net Reflection(反射)- 二
反射 Reflection 中访问方法 新建一个ClassLibrary类库: public class Student { public string Name { get; set; } publ ...
- Markdown使用心得
1. 标题的使用 在使用标题时,如果为了层次清晰,可以在"#"后加上"1. "或者"1.1. "这种序号. 每一级标题的正文结束后,最好加一 ...
- C# 抽象(4)
抽象类和普通类有区别嘛?在继承的时候,还是只能继承一次父类嘛? 答案: 抽象类除了在抽象方法和属性上面不能实现具体的代码之外和普通类没有区别.依旧符合类的基本特征.所以在继承的时候抽象类也是属于基类, ...
- 新增扩展程序功能打包提交新版 WARNING ITMS-90473 警告问题
1.问题描述 自从在主应用中加入SiriShortCut功能之后,打包程序上传至 iTunes Connect 就会出现警告,看其原因描述是CFBundleVersion主应用与子应用的不一致导致的 ...
- Mybatis中的多表查询 多对多
示例:用户和角色 一个用户可以有多个角色 一个角色可以赋予多个用户 步骤: 1.建立两张表:用户表,角色表 让用户表和角色表具有多对多的关系. 需要使用中间表,中间表中包含各自的主键,在中间表中是外键 ...