Oracle优化器基础知识

[TOC]
本博客介绍一下Oracle优化器范畴的基础知识点,访问数据的方法

一、访问数据的方法

Oracle访问表中数据的方法有两种,一种是直接表中访问数据,另外一种是先访问索引,如果索引数据不符合目标SQL,就回表,符合就不回表,直接访问索引就可以。
本博客先介绍直接访问数据的方法,下一篇博客在访问索引的方法

1、直接访问数据

Oracle直接访问表中数据的方法又分为两种:一种是全表扫描;另一种是ROWID扫描

1.1 全表扫描

全表扫描是Oracle直接访问数据的一种方法,全表扫描时从第一个区(EXTENT)的第一个块(BLOCK)开始扫描,一直扫描的到表的高水位线(High Water Mark),这个范围内的数据块都会扫描到

全表扫描是采用多数据块一起扫的,并不是一个个数据库扫的,然后我们经常说全表扫描慢是针对数据量很多的情况,数据量少的话,全表扫描并不慢的,不过随着数据量越多,高水位线也就越高,也就是说需要扫描的数据库越多,自然扫描所需要的IO越多,时间也越多

注意:数据量越多,全表扫描所需要的时间就越多,然后直接删了表数据呢?查询速度会变快?其实并不会的,因为即使我们删了数据,高位水线并不会改变,也就是同样需要扫描那么多数据块

1.2 ROWID扫描

ROWID也就是表数据行所在的物理存储地址,所谓的ROWID扫描是通过ROWID所在的数据行记录去定位。ROWID是一个伪列,数据库里并没有这个列,它是数据库查询过程中获取的一个物理地址,用于表示数据对应的行数。
用sql查询:

select t.* , rowid from 表格

随意获取一个ROWID序列:AAAWSJAAFAAAWwUAAA,前6位表示对象编号(Data Object number),其后3位文件编号(Relative file number),接着其后6位表示块编号(Block number), 再其后3位表示行编号(Row number)


在这里插入图片描述

ROWID编码方法是:A ~ Z表示0到25;a ~ z表示26到51;0~9表示52到61;+表示62;/表示63;刚好64个字符。

这里随意找张表查一下文件编号、区编号、行编号,查询后会返回rowid的一系列物理地址和文件编号(rowid_relative_fno(rowid))、块编号(rowid_block_number(rowid))、行编号(rowid_row_number(rowid))

select t.seq,
       rowid,
       dbms_rowid.rowid_relative_fno(rowid),
       dbms_rowid.rowid_block_number(rowid),
       dbms_rowid.rowid_row_number(rowid)
  from t_info t

SQL查询一下表格名称为TABLE的对象编码

select owner,object_id,data_object_id,status from dba_objects where object_name='TABLE';

相对文件id和绝对文件编码
相对文件id是指相对于表空间,在表空间唯一;绝对文件编码是指相当于全局数据库而言的,全局唯一;下面SQL查询一下相对文件id和绝对文件编码

select file_name,file_id,relative_fno from dba_data_files;

2、访问索引

对于Oracle数据库来说,B树索引是最常见的了,下面给出B树索引的图,图来自《基于Oracle的SQL优化》一书:

在这里插入图片描述

对于B树索引,分成两种类型的数据块,一种是索引分支块,另外一种是索引叶子块,索引根块是一种特殊的索引分支块。

影响逻辑读的缓存:

清Buffer Cache

alter system flush buffer_cache;//请勿随意在生产环境执行此语句

清数据字典缓存(Data Dictionary Cache)

alter system flush shared_pool;//请勿随意在生产环境执行此语句

2.1 索引唯一扫描

索引唯一性扫描(INDEX UNIQUE SCAN)是针对唯一性索引(UNIQUE INDEX)来说的,也就是建立唯一性索引才能索引唯一性扫描,唯一性扫描,其结果集只会返回一条记录。
创建唯一性索引SQL是:

create unique index 索引名 on 表名(列名)

例子,例子来自《基于Oracle的SQL优化》一书:

scott用户登录

SQL> create table emp_temp as select * from emp;//创建一个测试表
SQL> create unique index idx_emp_temp on emp_temp(empno);//创建唯一型索引
SQL> set autotrace on//设置执行计划显示
SQL> select * from emp_temp where empno =7369;//走索引唯一性扫描

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7369 SMITH      CLERK           7902 17-12月-80            800
        20



执行计划
----------------------------------------------------------
Plan hash value: 3451700904

--------------------------------------------------------------------------------

------------

| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)

| Time     |

--------------------------------------------------------------------------------

------------

|   0 | SELECT STATEMENT            |              |     1 |    87 |     1   (0)

| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| EMP_TEMP     |     1 |    87 |     1   (0)

| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN         | IDX_EMP_TEMP |     1 |       |     0   (0)

| 00:00:01 |

--------------------------------------------------------------------------------

------------


Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"=7369)

2.2 索引范围扫描

索引范围扫描(INDEX RANGE SCAN)适用于所有类型的B树索引,一般不包括唯一性索引,因为唯一性索引走索引唯一性扫描。 当扫描的对象是非唯一性索引的情况,where谓词条件为Between、=、<、>等等的情况就是索引范围扫描,注意,可以是等值查询,也可以是范围查询。如果where条件里有一个索引键值列没限定为非空的,那就可以走索引范围扫描,如果改索引列是非空的,那就走索引全扫描**

前面说了,同样的SQL建的索引不同,就可能是走索引唯一性扫描,也有可能走索引范围扫描。在同等的条件下,索引范围扫描所需要的逻辑读和索引唯一性扫描对比,逻辑读如何?索引范围扫描可能返回多条记录,所以优化器为了确认,肯定会多扫描,所以在同等条件,索引范围扫描所需要的逻辑读至少会比相应的唯一性扫描的逻辑读多1

继续上面的例子:

SQL> drop index idx_emp_temp;//删了刚才的唯一性索引

索引已删除。

SQL> create index idx_emp_temp on emp_temp(empno);//创建一个B树索引

索引已创建。

SQL> select * from emp_temp where empno=7369;//走索引范围扫描,因为empno没有限定为非空

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7369 SMITH      CLERK           7902 17-12月-80            800
        20



执行计划
----------------------------------------------------------
Plan hash value: 351331621

--------------------------------------------------------------------------------

------------

| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)

| Time     |

--------------------------------------------------------------------------------

------------

|   0 | SELECT STATEMENT            |              |     1 |    87 |     2   (0)

| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| EMP_TEMP     |     1 |    87 |     2   (0)

| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | IDX_EMP_TEMP |     1 |       |     1   (0)

| 00:00:01 |

--------------------------------------------------------------------------------

------------


Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"=7369)

Note
-----
   - dynamic sampling used for this statement (level=2)

2.3 索引全扫描

索引全扫描(INDEX FULL SCAN)适用于所有类型的B树索引(包括唯一性索引和非唯一性索引)。

索引全扫描过程简述:索引全扫描是指扫描目标索引所有叶子块的索引行,但不意思着需要扫描所有的分支块,索引全扫描时只需要访问必要的分支块,然后定位到位于改索引最左边的叶子块的第一行索引行,就可以利用改索引叶子块之间的双向指针链表,从左往右依次顺序扫描所有的叶子块的索引行

索引全扫描的例子:直接查emp表就好,因为empno是非空的

SQL> select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7369 SMITH      CLERK           7902 17-12月-80            800
        20

      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300
        30

      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500
        30


     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7566 JONES      MANAGER         7839 02-4月 -81           2975
        20

      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400
        30

      7698 BLAKE      MANAGER         7839 01-5月 -81           2850
        30


     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7782 CLARK      MANAGER         7839 09-6月 -81           2450
        10

      7788 SCOTT      ANALYST         7566 19-4月 -87           3000
        20

      7839 KING       PRESIDENT            17-11月-81           5000
        10


     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0
        30

      7876 ADAMS      CLERK           7788 23-5月 -87           1100
        20

      7900 JAMES      CLERK           7698 03-12月-81            950
        30


     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7902 FORD       ANALYST         7566 03-12月-81           3000
        20

      7934 MILLER     CLERK           7782 23-1月 -82           1300
        10


已选择14行。


执行计划
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   532 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

2.4 索引快速全扫描

索引快速全扫描和索引全扫描很类似,也适用于所有类型的B树索引(包括唯一性索引和非唯一性索引)。和索引全扫描类似,也是扫描所有叶子块的索引行,这些都是索引快速全扫描和索引全扫描的相同点

索引快速全扫描和索引全扫描区别:

  • 索引快速全扫描只适应于CBO(基于成本的优化器)
  • 索引快速全扫描可以使用多块读,也可以并行执行
  • 索引全扫描会按照叶子块排序返回,而索引快速全扫描则是按照索引段内存储块顺序返回
  • 索引快速全扫描的执行结果不一定是有序的,而索引全扫描的执行结果是有序的,因为索引快速全扫描是根据索引行在磁盘的物理存储顺序来扫描的,不是根据索引行的逻辑顺序来扫描的

条件是使用复合索引,而且使用Hint

/*+ index_ffs(表名 索引名) */
select /*+ index_ffs(emp_test pk_emp_test) */ empno from emp_test;

例子:


SQL> create table emp_test (empno number,ename varchar2(50));

表已创建。

SQL> alter table emp_test add constraint pk_emp_test primary key (empno,ename);

表已更改。

SQL> insert into emp_test select empno,ename from emp;

已创建14行。

SQL> commit;

提交完成。

SQL> select count(1) from emp_test;

SQL> select /*+ index_ffs(emp_test pk_emp_test) */ empno from emp_test;

     EMPNO
----------
      7369
      7499
      7521
      7566
      7654
      7698
      7782
      7788
      7839
      7844
      7876

     EMPNO
----------
      7900
      7902
      7934

已选择14行。


执行计划
----------------------------------------------------------
Plan hash value: 3550420785

--------------------------------------------------------------------------------

----

| Id  | Operation            | Name        | Rows  | Bytes | Cost (%CPU)| Time
   |

--------------------------------------------------------------------------------

----

|   0 | SELECT STATEMENT     |             |    14 |   182 |     2   (0)| 00:00:

01 |

|   1 |  INDEX FAST FULL SCAN| PK_EMP_TEST |    14 |   182 |     2   (0)| 00:00:

01 |

--------------------------------------------------------------------------------

----


Note
-----
   - dynamic sampling used for this statement (level=2)

2.5 索引跳跃式扫描

索引跳跃式扫描(INDEX SKIP SCAN)适用于所有类型的复合B树索引(包括唯一性索引和非唯一性索引),索引跳跃式扫描可以使那些在where条件中没有目标索引的前导列指定查询条件但是有索引的非前导列指定查询条件的目标SQL依然可以使用跳跃索引,定义解释有点绕,举个例子说明

假如新建了复合索引:

create index 索引名 on 表名(列名1,列名2)

这里新建了复合索引,假如查询如:

select * from 表名 where 列名1 = 条件1

假如改目标SQL符合索引跳跃式扫描的条件,即使,只有列名1这个前导列,还是可以走索引跳跃式扫描的,这个就是跳跃式扫描,不需要如下sql,全部索引列都定位到

select * from 表名 where 列名1 = 条件1 and 列名2 = 条件2

当然索引跳跃式扫描并不是说适用所有情况,不加前导列,有时候是不走跳跃式扫描的,Oracle中的索引跳跃式扫描仅仅适用于那些目标索引前导列的distinct值数量较少,后续非导列的可选择性又非常好的情况,索引跳跃式扫描的执行效率一定会随着目标索引前导列的distinct值数量的递增而递减的

拓展补充

对于索引来说,如果索引条件有null值,是不走索引的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 4,866评论 0 9
  • 转 # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    吕品㗊阅读 9,617评论 0 44
  • 1.数据库三范式是什么? 第一范式:表中每个字段都不能再分。 第二范式:满足第一范式并且表中的非主键字段都依赖于主...
    杰伦哎呦哎呦阅读 2,822评论 0 28
  • 怎么说怎么讲,人总要向生活低头,如果在一个地方不低头,在另一个地方也得低头。 很多东西都是正常的沟通交流,并不存在...
    Mandy_e814阅读 731评论 0 0
  • 工作压力好大啊,本来就刚毕业的小菜鸟,越来越承受不来,感觉身体也受不住 也只能在简书发个牢骚了
    鹤小姐阅读 149评论 0 0