内容简介:

1.普通B-TREE 索引;

2.唯一B-TREE 索引;

3.复合索引;

ORACLE 默认的索引类型为B-TREE 索引,表中的行标识符(ROWID)和行相关的列值被存储在一个平衡树的树状结构的索引块中;使用B-TREE索引有以下几个原因:

▢ 提高SQL语句的性能;

▢ 强制执行主键和唯一键约束的唯一性;

▢ 减少通过主键和外键约束关联的父表和子表间潜在的锁定问题 ;

1.普通B-TREE 索引

在一张未建立任何索引的500万行人员信息表中根据人员ID查询人员信息

select id,name,gender,homeaddr from th01 where id=998698;

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

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

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

| 0 | SELECT STATEMENT | | 1 | 38 | 16715 (1)| 00:03:21 |

|* 1 | TABLE ACCESS FULL| TH01 | 1 | 38 | 16715 (1)| 00:03:21 |

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

Predicate Information (identified by operation id):

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

1 - filter("ID"=998698)

Statistics

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

61222 consistent gets

61208 physical reads

通过观察执行计划,CBO优化器执行了全表扫描,一致读取61222个块,61208个物理读,基于性能的考虑和表结构的分析,为其B-TREE索引:

SQL> CREATE INDEX IND_TH01_ID ON TH01(ID) TABLESPACE TBS02;

Index created.

Elapsed: 00:00:33.03

SQL> execute dbms_stats.gather_table_stats('sywu','th01',cascade=>true);

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.17

SQL> @/oracle/getind

TABLE_NAME     INDEX_NAME    COLUMN_NAME    SIZE_GB    INDEX_TY   STATUS    LOGGING    DEGREE    NUM_ROWS    DISTINCT_KEYS

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

TH01                    IND_TH01_ID          ID                    .091796875       NORMAL VALID             YES               1            DISABLED        5000000   5000000

显然对于高基数的列创建B-TREE索引是明智之选,对表进行分析后再次查询:

SQL>select id,name,gender,homeaddr from th01 where id=998698;

Elapsed: 00:00:00.00

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

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

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

| 0 | SELECT STATEMENT | | 1 | 38 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 38 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_ID | 1 | | 3 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("ID"=998698)

Statistics

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

5 consistent gets

0 physical reads

基于成本的考虑,CBO优化器选择了通过索引的方式读取数据,一致读取5个块,有效减少了额外的物理读;做个基于索引列的统计查询:

SQL> select count(id) from th01;

Elapsed: 00:00:00.15

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

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

| 0 | SELECT STATEMENT | | 1 | 6 | 3170 (1)| 00:00:39 |

| 1 | SORT AGGREGATE | | 1 | 6 | | |

| 2 | INDEX FAST FULL SCAN| IND_TH01_ID | 5000K| 28M| 3170 (1)| 00:00:39 |

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

Statistics

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

11810 consistent gets

11794 physical reads

CBO 优化器选择了全索引扫描,依旧消耗额外的资源;但当统计列发生改变时:

SQL> select count(*) from th01;

Elapsed: 00:00:00.14

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

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

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

| 0 | SELECT STATEMENT | | 1 | 16707 (1)| 00:03:21 |

| 1 | SORT AGGREGATE | | 1 | | |

| 2 | TABLE ACCESS FULL| TH01 | 5000K| 16707 (1)| 00:03:21 |

Statistics

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

61221 consistent gets

61208 physical reads

此时CBO 优化器选择了全表扫描,并消耗更多的资源;

2.唯一B-TREE 索引:

在为表创建(主键、唯一约束)时,ORACLE 会默认创建一个B-TREE索引,这样既保证了数据的唯一性也提高了数据的检索效率:

SQL> alter table th01 add constraints cs_th01_uq unique(idcard);

Table altered.

Elapsed: 00:00:56.11

TABLE_NAME      INDEX_NAME     COLUMN_NAME     SIZE_GB    INDEX_TY      STATUS     LOGGING        DEGREE    COMPRESS    NUM_ROWS    DISTINCT_KEYS

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

TH01             CS_TH01_UQ                  IDCARD                .15625               NORMAL   VALID              YES                  1              DISABLED    4969898           4969898

以IDCARD查询人员信息:

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

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 35 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("IDCARD"='562456864646565545')

Statistics

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

3 consistent gets

0 physical reads

做为默认创建的索引,它依旧能高效的工作,但ORACLE是不允许将其作为独立的索引删除的,只能通过删除约束的方式删除;对于主键,它的情况要复杂些,因为还要考虑外键的约束;基于这种方式创建的索引,当约束被删除时还要重新创建索引,显然在一张大表上花费的代价和时间是昂贵的; so,采用如下的方式合理的建立约束和索引:

SQL> alter table th01 add constraints CS_TH01_UQ unique(idcard)

2* using index tablespace tbs03 ;

Table altered.

Elapsed: 00:00:59.27

倘若有一天业务发生了改变,唯一约束已经不是必须的,但索引是必须的,那只需要删除约束保留索引:

SQL> alter table th01 drop constraints CS_TH01_UQ keep index;

Table altered.

Elapsed: 00:00:00.01

再次通过IDCARD 查询人员信息:

SQL> select id,name,idcard from th01 where idcard='56234256878945';

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

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

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

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 35 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("IDCARD"='56234256878945')

Statistics

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

1 recursive calls

0 db block gets

3 consistent gets

只创建唯一索引:

SQL> create unique index ind_th02 on th02(idcard) tablespace tbs03;

唯一索引与唯一约束相比,唯一索引只创建索引而不添加约束,它保证索引列数值唯一性,允许有空值;

3.复合索引:

可以在多个列上创建索引,其结果称为复合索引或组合索引:

SQL> create index ind_th01_union on th01(id,name,idcard) tablespace tbs03;

当查询的WHERE子句引用了索引的所有列或者只是前导列,CBO会使用复合索引

SQL>select id,name,idcard from th01 where idcard='9876534655635666' and id=68956254 and name='张三';

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

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

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

| 0 | SELECT STATEMENT | | 1 | 35 | 3 (0)| 00:00:01 |

|* 1 | INDEX RANGE SCAN| IND_TH01_UNION | 1 | 35 | 3 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

1 - access("ID"=68956254 AND "NAME"='张三' AND

"IDCARD"='9876534655635666')

Statistics

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

1 recursive calls

0 db block gets

3 consistent gets

2 physical reads

通过查询结果,对于之前创建的单列索引(IND_TH01_ID、CS_TH01_UQ),优化器已不再使用;对于复合索引( IND_TH01_UNION) 来说, id | id, name| id,name,idcard 三个组合都被认为是前导列,假如我只是在WHERE 子句中引用了第一个主导列ID,那么优化器依旧会选择复合索引(IND_TH01_UNION )忽略单列索引( IND_TH01_ID)

SQL> select * from th01 where id=698698;

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

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

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

| 0 | SELECT STATEMENT | | 1 | 77 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_UNION | 1 | | 3 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("ID"=698698)

Statistics

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

0 db block gets

5 consistent gets

假如where 子句中的条件不符合复合索引前导列的要求,那么优化器会忽略复合索引( IND_TH01_UNION)选择单列索引(CS_TH01_UQ):

SQL> select * from th01 where idcard='5623546566564665';

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

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

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

| 0 | SELECT STATEMENT | | 1 | 77 | 3 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 3 (0)| 00:00:01 |

|* 2 | INDEX UNIQUE SCAN | CS_TH01_UQ | 1 | | 2 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("IDCARD"='5623546566564665')

Statistics

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

1 recursive calls

0 db block gets

3 consistent gets

1 physical reads

对于此时的查询条件 where idcard='5623546566564665' 已经不再符合( id | id, name| id,name,idcard) 复合索引前导列的条件,优化器选择单列索引( CS_TH01_UQ);又假如,我的WHERE 子句条件符合复合索引前导列要求但不是全部满足:

SQL> select * from th01 where id=698698 and name='张三';

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

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

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

| 0 | SELECT STATEMENT | | 1 | 77 | 4 (0)| 00:00:01 |

| 1 | TABLE ACCESS BY INDEX ROWID| TH01 | 1 | 77 | 4 (0)| 00:00:01 |

|* 2 | INDEX RANGE SCAN | IND_TH01_UNION | 1 | | 3 (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("ID"=698698 AND "NAME"='张三')

Statistics

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

3 consistent gets

0 physical reads

通过分析(where id=698698 and name='张三' )符合复合索引前导列要求,优化器选择复合索引( IND_TH01_UNION) 忽略单列索引( IND_TH01_ID);

创建复合索引时,排序是个很大的问题,ORACLE 建议将最频繁访问的列放在索引中最靠前的位置,应避免使用低基数的列作为复合索引的前导列.

转载于:https://www.cnblogs.com/lanston/p/3485466.html

ORACLE B-TREE(B树)索引相关推荐

  1. Oracle数据库解决NULL值不走B树索引

    B树索引我们可以把它看成是书的目录,在这个目录中主要记录的是索引所对应的表列的值和这个值所对应的ROWID.在通常情况下,我们在表中增加索引的目的是增加表的查询性能,但是有几种情况,即使你在表中加入了 ...

  2. oracle b树索引原理,Oracle索引原理精简总结

    尝试用最少的字数介绍oracle的几种常用索引原理,主要是想简单分析其存储结构来说明其检索方式,和解释为什们某种索引使用与某种场合.(数据结构中最简单的ArrayList和LinkedList的使用场 ...

  3. oracle通过执行计划cost,Oracle 执行计划(5)—cost成本之索引范围扫描-B树索引

    Oracle 执行计划(5)-cost成本之索引范围扫描-B树索引 SQL>  select * from t1 where a<600 ; 已选择599行. 已用时间:  00: 00: ...

  4. oracle执行计划cost单位,Oracle 执行计划(5)—cost成本之索引范围扫描-B树索引

    Oracle 执行计划(5)-cost成本之索引范围扫描-B树索引 SQL>  select * from t1 where a<600 ; 已选择599行. 已用时间:  00: 00: ...

  5. Oracle索引梳理系列(二)- Oracle索引种类及B树索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  6. 从MySQL Bug#67718浅谈B+树索引的分裂优化

    从MySQL Bug#67718浅谈B+树索引的分裂优化 1月 6th, 2013 发表评论 | Trackback 问题背景 今天,看到Twitter的DBA团队发布了其最新的MySQL分支:Cha ...

  7. 5.算法进阶——kafka消息查询(二分法)——稀疏索引与B+树索引的对比

    Kafka介绍 Kafka 是一款性能强大且相当常用的分布式消息队列,常常用于对流量进行消峰.解耦系统和异步处理部分逻辑以提高性能的场景. 在kafka中,所有的消息都以日志的形式存储.这种日志只允许 ...

  8. 数据库系统——B+树索引

    原文来自于:http://dblab.cs.toronto.edu/courses/443/2013/05.btree-index.html 1. B+树索引概述 在上一篇文章中,我们讨论了关于ind ...

  9. 【数据结构】B-Tree, B+Tree, B*树介绍

    [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tree索引,InnoDB还支持B+Tree索引,Memory ...

  10. mysql b tree图_MySQL索引--B-Tree(B+Tree)图文详解

    看了很多关于索引的博客,讲的大同小异.但是始终没有让我明白关于索引的一些概念,如B-Tree索引,Hash索引,唯一索引....或许有很多人和我一样,没搞清楚概念就开始研究B-Tree,B+Tree等 ...

最新文章

  1. tableau必知必会之通过 Tableau 计算挖掘数据真相
  2. bzoj 3572 [Hnoi2014]世界树——虚树
  3. 来不及想标题了,我要去打包收藏了 | 本周值得读
  4. opencv进阶学习笔记2:numpy操作图像,色彩空间,查找指定颜色范围,通道分离与合并
  5. kvm连接服务器显示不全有重影,KVM延长器系列常见问题及解决方法
  6. ASP.NET Core 中的那些认证中间件及一些重要知识点
  7. delphi Post数据到网页
  8. twrp3.3.0刷n9002_插画师必备笔刷,送你5套iPad5.0新出300款大神笔刷
  9. LeetCode 102. 二叉树的层次遍历(BFS)
  10. 微软总裁比尔.盖茨给即将走出学校、踏入社会的青年一代下列11点忠告
  11. 2.7.3-YARN-获取debug命令:resourceManager+nodeManager
  12. 【渝粤教育】广东开放大学 hadoop数据管理 形成性考核
  13. 常用计算机检索算符,在计算机检索中,常用的布尔逻辑算符有哪几种
  14. WDS+MDT部署Windows7操作系统2—;导入启动映像和安装映像
  15. java绘制图片验证码两种方式实现,点击【图片】刷新和点击【看不清换一张】刷新
  16. 如何搭建一个属于自己的博客网站?(小白教程)
  17. asp.net core ABP模板本地化设置
  18. 0805,0603,1206这些封装名字的由来
  19. 水岸秀墅|千年石湖独一墅
  20. 程序编写经验教训_编写38本编程书籍的经验教训

热门文章

  1. 第一次参加学校的ACM比赛所学及感想
  2. linux服务器配置trunk,在Linux配置VLAN Trunk
  3. anaconda 怎么安装xlrd_Anaconda 安装 tensorflow 和 keras
  4. 如何查询高考2021普体成绩,中考体育成绩对照表2020
  5. php+ok,php fscokopen实现数据异步调用代码
  6. java反射随意值_Java反射笔记
  7. java 执行jar_windows下如何用java指令运行jar包?
  8. kibana 更新 索引模式_Kibana对索引动态加字段显示
  9. java 倒序分页_翻动100万级的数据(自定义的MSSQL分页查询过程)
  10. JAVA中常用的逻辑运算符_Java中常用的运算符