Oracle 优化器_访问数据的方法_单表
Oracle 在选择执行计划的时候,优化器要决定用什么方法去访问存储在数据文件中的数据。我们从数据文件中查询到相关记录,有两种方法可以实现:1.直接访问表记录所在位置。2.访问索引,拿到索引中对应的rowid,然后根据rowid 去表中获取相应的数据。(有些情况,不需要再去表中取数据就可以得到相应的结果,那么就会直接返回)。
访问表的方法
全表扫描
全表扫描,Oracle 在取数据库数据的时候,从该表在硬盘上的第一个数据块开始,扫描到该表的最高水位线所在的数据块。在读的时候,会使用多块读的技术,将全表扫描一遍表数据,然后将不满足的数据剔除掉,返回需要的数据。Oracle 全表扫描的速度取决于最高水位线的大小。当表中的高水位线越大,需要消耗的资源(主要是I/O资源)越多。这样一来,耗费的时间也会增加。
高水位:在Oracle中,表是属于表空间的,如果建表的时候,没有设置表空间,那么就会将当前用户的默认空间作为表格所在的表空间。如果一直往表中插入数据,分配给表的空间用完了,高水位线就会向上移动。如果用delete语句删除数据,水位线也不回降下来。这就会导致,有的表虽然只有几条数据,但是全表扫描就会很消耗性能。所以在进行大量的delete操作的时候,需要执行降水位的操作。
ROWID 扫描
rowId 类似于指针的概念。rowid和数据块中的行数据是一一对应的。我们知道某一行对应的rowid后,可以直接通过rowid去直接访问相应数据对应的数据行。Oracle 使用row取数据有两种:1、直接用rowId从取得相应数据。2、根据索引获得rowId,然后取数据。
我们获取rowid的方法很简单,在每行记录中,都有一个Oracle内置的伪列rowId 直接在查询的时候去获取就可以了(注:这里需要将rowId 进行重命名,不然无法返回,不知道是不是笔者个人原因还是都需要这么写)。以emp表为例:
SELECT ENAME ,EMPNO, rowId dataRowId FROM EMP;
查出来的结果如下:
SMITH 7368 AAAtkkAAGAABqYkAAA
SMITH 7369 AAAtkkAAGAABqYkAAB
ALLEN 7499 AAAtkkAAGAABqYkAAC
WARD 7521 AAAtkkAAGAABqYkAAD
JONES 7566 AAAtkkAAGAABqYkAAE
MARTIN 7654 AAAtkkAAGAABqYkAAF
BLAKE 7698 AAAtkkAAGAABqYkAAG
CLARK 7782 AAAtkkAAGAABqYkAAH
SCOTT 7788 AAAtkkAAGAABqYkAAI
KING 7839 AAAtkkAAGAABqYkAAJ
TURNER 7844 AAAtkkAAGAABqYkAAK
ADAMS 7876 AAAtkkAAGAABqYkAAL
JAMES 7900 AAAtkkAAGAABqYkAAM
FORD 7902 AAAtkkAAGAABqYkAAN
MILLER 7934 AAAtkkAAGAABqYkAAO
这里查出的rowId可以直接作为where条件去进行查询,SQL如下:
SELECT ENAME ,EMPNO, rowId dataRowId FROM EMP where rowId='AAAtkkAAGAABqYkAAA';
执行结果:
这条SQL的执行计划如下:
Plan hash value: 1116584662 -----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 22 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY USER ROWID| EMP | 1 | 22 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------- Note
-----
从Id为1的这一行可以看出,执行计划走的是 BY USER ROWID 这个执行计划。我们对比下通过主键EMPNO去查询得到的执行计划:
执行SQL如下:
SELECT ENAME ,EMPNO, rowId dataRowId FROM EMP where EMPNO='';
执行结果跟通过rowId执行得到的执行结果一致:
其执行计划如下:
Plan hash value: 2137789089 ---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8168 | 16336 | 29 (0)| 00:00:01 |
| 1 | COLLECTION ITERATOR PICKLER FETCH| DISPLAY | 8168 | 16336 | 29 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------- Note
-----
可以看出,通过rowId得到的结果比使用主键进行查找的消耗要小的多,因为主键是先通过主键索引找到rowId,然后进行数据的提取操作,而rowId则是直接从数据文件中提取数据。
访问索引的方法
索引结构(B树索引)
在说通过索引扫描数据之前,先介绍下什么是索引。Oracle数据库中用的最多的是B树索引。B树索引的结构如下图所示:
索引包含两个部分,一部分是索引分支块,另外一部分是叶子块。在数据根据索引进行扫描的时候,可以根据数据的内容,计算得出一个索引的值。然后根据索引值,得到响应的rowId,然后根据rowid,去数据文件取出相应的数据。Oracle 通过索引访问表里的记录的效率并不会随着相关表的数据量的递增而显著降低,所以索引访问数据的时间是基本稳定可控的。
索引唯一性扫描(INDEX UNIQUE SCAN)
索引唯一性扫描,是针对唯一性索引(unique scan)进行的扫描。当它的where条件是等于号的时候,扫描结果至多会返回一条数据记录。例如:sql语句:
select * from emp where EMPNO = 7368
执行计划:
Plan hash value: 2949544139 --------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 37 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 37 | 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("EMPNO"=7368) Note
索引范围扫描(INDEX RANGE SCAN)
范围索引扫描,使用于所有类型的B树索引,当扫描对象是唯一性索引时,目标的SQL条件一定是范围条件,例如 where 条件为between、<、> 等。
例如,SQL语句为:
select * from emp where EMPNO > 7933
执行计划为:
Plan hash value: 2787773736 ----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 37 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| EMP | 1 | 37 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | PK_EMP | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("EMPNO">7933) Note
通过对比范围索引和唯一索引可以看出,即使使用同样的索引,范围索引也比唯一索引消耗更多的CPU,因为范围索引至少要多一次逻辑读。
索引全扫描(INDEX FULL SCAN)
索引在做全扫描的时候,要求索引不能为空。不然会漏掉null 的字段。索引全扫描在默认情况下,直接从第一个叶子节点,通过叶子节点之间相互的链表指针进行跳转。既能保证数据有序,又避免了对索引真正值的排序操作。
sql语句:
SELECT EMPNO FROM EMP
执行计划 :
Plan hash value: 179099197 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 16 | 64 | 1 (0)| 00:00:01 |
| 1 | INDEX FULL SCAN | PK_EMP | 16 | 64 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------- Note
索引快速全扫描(INDEX FAST FULL SCAN)
索引快速扫描和索引全扫描类似,与之相比有如下区别:
1.快速全扫描只适用于CBO。
2.索引快速全扫描可以使用多块读,也可以并发执行。
3.索引快速全扫描结果不一定有序。
索引跳跃式扫描(INDEX SKIP SCAN)
索引跳跃式扫描适用于组合索引。适用场景举例:当前索引有两个列,为:C1,C2。当我们的SQL语句where条件中,没有对C1进行筛选,而是对C2进行了筛选。那么有时候就会出现使用跳跃式索引扫描的情况。Oracle 中索引跳跃扫描适用于前导列可选择性较差,后续列的可选择性又非常好的场景。因为前导列包含的distinct值越少,跳跃次数也就越少,索引效率也就越高。
Oracle 优化器_访问数据的方法_单表的更多相关文章
- Oracle优化器基础知识之访问数据的方法
目录 一.访问数据的方法 1.直接访问数据 2.访问索引 一.访问数据的方法 Oracle访问表中数据的方法有两种,一种是直接表中访问数据,另外一种是先访问索引,如果索引数据不符合目标SQL,就回表, ...
- Oracle索引梳理系列(一)- Oracle访问数据的方法
版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...
- Oracle 优化器_表连接
概述 在写SQL的时候,有时候涉及到的不仅只有一个表,这个时候,就需要表连接了.Oracle优化器处理SQL语句时,根据SQL语句,确定表的连接顺序(谁是驱动表,谁是被驱动表及 哪个表先和哪个表做链接 ...
- Oracle优化器介绍
Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. RBO优化器 ...
- Oracle 优化器
http://blog.csdn.net/it_man/article/details/8185370一.优化器基本知识 Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执 ...
- ORACLE优化器RBO与CBO介绍总结
RBO和CBO的基本概念 Oracle数据库中的优化器又叫查询优化器(Query Optimizer).它是SQL分析和执行的优化工具,它负责生成.制定SQL的执行计划.Oracle的优化器有两种,基 ...
- [转]ORACLE优化器RBO与CBO的区别
RBO和CBO的基本概念 Oracle数据库中的优化器又叫查询优化器(Query Optimizer).它是SQL分析和执行的优化工具,它负责生成.制定SQL的执行计划.Oracle的优化器有两种,基 ...
- 【SQL Server性能优化】删除大量数据的方法比较
原文:[SQL Server性能优化]删除大量数据的方法比较 如果你要删除表中的大量数据,这个大量一般是指删除大于10%的记录,那么如何删除,效率才会比较高呢? 而如何删除才会对系统的影响相对较小呢? ...
- 选用适合的ORACLE优化器
ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性) 设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER ...
随机推荐
- Servlet高级应用
会话只是指一段指定的时间间隔. 会话跟踪是维护用户状态(数据)的一种方式.它也被称为servlet中的会话管理. Http协议是一个无状态的,所以我们需要使用会话跟踪技术来维护用户状态. 每次用户请求 ...
- jdk1.8HashMap底层数据结构:散列表+链表+红黑树,jdk1.8HashMap数据结构图解+源码说明
一.前言 本文由jdk1.8源码整理而得,附自制jdk1.8底层数据结构图,并截取部分源码加以说明结构关系. 二.jdk1.8 HashMap底层数据结构图 三.源码 1.散列表(Hash table ...
- 记kepServer读写西门子PLC
在程序开发过程中为了测试方法或者验证某个属性的值是否正确 经常通过Kepserver 的 OPC Quick Client来手动置点或者读取点位 例如 这里显示的值都是经过转化后得到的十进制值,那我们 ...
- 【Python-Django后端】用户注册通用逻辑,用户名、手机号重名检测,注册成功后状态保持!!!
用户注册后端逻辑 1. 接收参数 username = request.POST.get('username') password = request.POST.get('password') pas ...
- 跟着大彬读源码 - Redis 8 - 对象编码之字典
目录 1 字典的实现 2 插入算法 3 rehash 与 渐进式 rehash 总结 字典,是一种用于保存键值对的抽象数据结构.由于 C 语言没有内置字典这种数据结构,因此 Redis 构建了自己的字 ...
- WPF控件截图
//截图 RenderTargetBitmap RenderVisaulToBitmap(Visual vsual, int width, int height) { ...
- Quartz CronTrigger定时器表达式大全
CronTrigger是基于Calendar-like调度的.当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger.正如它的名字所暗示的那样,CronTrigg ...
- 《HTTP权威指南》--阅读笔记(一)
HTTP: HyperText Transfer Protocol 测试站点:http://www.joes-hardware.com URI包括URL和URN URI: Uniform Resour ...
- 8、JAVA中的用户输入(I/0交互过程)
这里在数组的学习中用到了用户输入,也就是交互模式,日常的数据,不可能每一次都是程序员定义好的,终究需要用户与程序之间进行交互,机器等待用户输入,用户通过键盘输入所需数据(数据包括,字符,字串,数值等) ...
- LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)
本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...