在关系型数据库中,用户查找数据与行的物理位置无关紧要。为了能够找到数据,表中的每一行均用一个rowid来标识,rowid能够标识数据库中某一行的具体位置。当Oracle数据库中存储海量的记录时,就意味着大量的rowid标识,这样Oracle如何能够快速找到指定的rowid呢?这时就需要使用索引对象,它可以提供服务器在表中快速查找记录的功能。
1、索引概述
如果一个数据表中存有海量的数据行,当对表执行指定条件的查询时,常规的查询方法会将所有的记录都读取出来,然后再把读取的每一条记录与查询条件进行比对,最后返回满足条件的记录。这样进行操作的时间开销和IO开销都很大。对于这种情况,就可以考虑通过建立索引来减少系统开销。
如果要在表中查询指定的记录,在没有索引的情况下,必须遍历整个表,而有了索引之后,只需要在索引中找到负荷查询条件的索引字段值,就可以通过保存在索引中的rowid快速找到表中对应的记录。例如,如果将表看做一本书,索引的作用则类似与书中的目录。在没有目录的情况下,要在书中查找指定的内容必须翻阅全书,而有了目录之后,只需要通过目录就可以快速找到包含所需要内容的页码(相当于rowid)。
Oracle对所以与表的管理有很多相同的地方,不仅需要在数据字典里保存所以的定义,还需要在表空间中为它分配实际的存储空间。创建索引时,Oracle会自动在用户的默认表空间或指定的表空间创建一个索引段,为索引数据提供空间。
用户可以在Oracle中创建多种类型的索引,以适应各种表的特点。按照索引数据的存储方式可以将索引分为B树索引、位图索引、反向键索引和基于函数的索引。按照索引列的唯一性可以分为唯一性索引和非唯一性索引;按照索引列的个数可以分为单列索引和复合索引。
建立和规划索引时,必须选择合适的表和列,如果选择的表和列不合适,不仅无法提高查询速度,反而会极大降低DML操作的速度,所以建立索引必须注意一下几点:
a)索引应该建立在where子句频繁引用表列上,如果在达标上频繁使用某列或某几列作为条件执行索引操作,并且检索行数低于总行数15%,那么应该考虑在这些列上建立索引。
b)如果经常需要基于某列或某几个列执行排序操作,那么这些列上建立索引可以加快数据排序速度。
c)限制表的索引个数。索引主要用于加快查询速度,但会降低DML操作的速度。索引越多,DML操作速度越慢,尤其会极大地影响INSERT和DELETE操作的速度。因此,规划索引时,必须仔细权衡查询和DML的需求。
d)指定索引块空间的使用参数。基于表建立索引时,Oracle会将相应表列数据添加到索引块。为索引块添加数据时,Oracle会按照pctfree参数在索引块上预留部分空间,该预留部分空间是为将来的insert操作准备的。如果将来在表上执行大量Insert操作,那么应该在建立索引时设置较大的pctfree。
e)将表和索引部署到相同的表空间,可以简化表空间管理;将表和索引部署不同的表空间,可以提高访问性能。
f)当大表上建立索引时,,使用nologging选项可以最小化重做记录。使用nologging选项可以节省重做日志空间、降低索引建立时间、提高索引并行建立的性能。
g)不要在小表上建立索引
h)为了提高多表连接的性能,应该在连接列上建立索引。
index entry的组成部分
indexentry entry header 存放一些控制信息
key column length 某一个key的长度
key column value 某一个key的值
rowid 指针,具体指向某一个数据
2、创建索引
在创建索引时,Oracle首先对将要建立索引的字段进行排序,然后将排序后的字段值和对应的记录的rowid存储在索引段中。建立索引可以使用create index语句,通常由表的所有者来建立索引。如果要以其他用户身份建立索引,则要求用户必须具有create any index系统权限或者相应表的index对象权限。
2.1、建立B树索引
B树索引时Oracle数据库最常用的索引类型(也是默认的),它是以B树结构组织并存放索引数据的,默认情况下,B树索引中的数据是以升序方式排列的。如果表包含的数据非常多,并且经常在where子句中引用某列或某几个列,则应该基于该列或这个几个列建立B树索引。B树索引由根块、分支块和叶块组成,其中主要数据都集中在叶子节点。
根块:索引顶级块,它包含指向下一级节点的信息。
分支块:它包含指向下一级节点(分支块或叶块)的信息。
叶块:通常也称为叶子块,它包含索引入口数据,索引入口包含索引列的值和记录行对应的物理地址rowid。
在B树索引中无论用户要搜索哪个分支的叶块,都可以保证 所经过的索引层次是相同的。Oracle采用这种方式的索引,可以确保无论索引条目位于何处,都只需要话费相同的IO即可获取它,这就是为什么被称为B树索引(B是英文BALANCED的缩写)。
例如,使用这个B树索引搜索编号为A004节点时,首先要访问根节点,从根节点中可以发现下一步应该搜索左边的分支,由于值A004小于B001,因此不需要第二次读取数据,而直接读取左边的分之节点。从左边的分之节点,可以判断出,要搜索的索引条目位于右侧的第一个叶子节点中。在那里可以很快找到要查询的索引条目,并根据索引条目中的rowid进而找到所有要查询的记录。
例子:
create index emp_deptno_index on (deptno) pctfree 25 tablespace test;
PCTFREE子句指定为将来槽所预留的空闲空间,子句tablespace用于指定索引段的表空间。假设表已经包含大量数据,那么在建索引时应该仔细规划pctfree的值,以便为以后的Insert操作预留空间。
2、建立位图索引
索引的作用简单来说就是能够通过给定的索引列值,快速地找到对应的记录。在B树索引中,通过在索引中保存的索引列的值以及记录的物理地址rowid来实现快速查找。但是对于一些特殊的表,B树索引的效率可能会很低。例如,在某个具有性别列的表,该列的所有取值只能是男或者女,如果在性别列上创建B树索引,那么创建的B数只有两个分支,,那么使用该索引对该表进行检索时,将返回一半的记录,这样就失去了所以的基本作用。
当列的基数很低时,为其建立B树索引显然不合适。“基数低”表示在索引列中,所有取值的数据量比表中行的数量少。如性别列只有两个取值;再比如某个用于10000行的表,它的一个列包含100个不同的取值,则该列还满足低基数的要求,因为该列与行数的比例为1%,Oracle推荐当一个列的基数小于1%时,这些列不再合适建立B树索引,而适用于位图索引。但在表中低基数的列上建立位图索引时,系统将对表进行一次全表扫描,为遇到的个取值构建图标。
2.1位图索引的原理
如果在性别列上建立了位图索引,对于性别这个列,针对每行的rowid(rowid可理解为每行的物理位置),位图索引形成两个向量,男向量位10100***,向量的每一位表示改行是否是男,如果是则位1,否为0,同理,女向量位01011***,(可理解为给每行数据的性别列中位产生两个向量,分别为男向量和女向量:男向量中值为男用1表示,值不是男用0表示;同理女向量中值为女用1表示,值不是女的用0表示)
rowid 1 2 3 4 5 *****
男 1 0 1 0 0
女 0 1 0 1 1
2.2、位图索引检索数据的过程
当我们使用查询语句select * from table where a ='男' and b='未婚';的时候,首先去除男向量,然后取出未婚的向量,将两个向量做and操作,这时生成新向量00100,为1时则表示满足查询要求的数据。
2.3、位图索引的限制或者弊端
位图索引在读密集的环境中能很好地工作,但是对于写密集的环境则极不合适,原因在于,一个位图索引键值指向多行。如果一个会话修改了有索引的列的数据,那么大多数情况下,这个索引键值(索引条目)指向的所有行都会被锁定。Oracle无法锁定一个位图索引键值的单独一位,而会锁定整个位图索引条目,倘若其他会话修改也需要更新同意的这个位图索引条目,就会被卡主,这样就大大影响了并发性。
位图索引时为数据仓库(也就是查询环境设计的),位图索引特别不适合OLTP系统,位图索引不适合与DML频繁的环境,适用于DSS系统,不适合频繁修改的系统,弊端是严重影响并发性。因为update索引列值的时候,会锁定新值和旧值指向的所有数据行,所以使用位图索引要慎重。
2.4、创建位图索引
create bitmap index emp_saary_bmp on employees(salary) tablespace test;
初始化参数create_bitmap_area_size用于指定建立位图索引时分配的位图区大小,默认值为8M,该数值越大建立位图索引的速度越快。为了加快创建位图索引,应将该参数设置更大些。因为该参数是静态参数,所以修改后必须重启数据块才能生效。
3、反向键索引
Oracle中系统会自动为表的主键建立索引,这个默认是B树索引,通常用户希望表的主键是一个自动增长的序列编号,这样的列就是所谓的单挑递增序列编号列。当在这种顺序递增的列上建立普通的B数索引时,如果表的数据量非常大,将导致索引数据分布不均。随着数据行的插入,索引数的层级增长很快,搜索索引发生的IO读写次数和索引树的层级数成正比,也就是说,一棵具有5个层级的B树索引,在最终读取到索引数据时最多可能发生多大5次IO操作,因而减少索引的层级树是索引性能调整的一个重要方法。如果索引列的数据以严格的有序的方式插入,那么B树索引树将变成一棵不对称的歪树。
反向键索引时一种特殊类型的B树索引,在顺序递增列上建立索引时非常有用。反向键索引的原理非常简单,在存储结上与常规的B树索引相同,然而,如果用户使用序列在表中输入记录,则反向键索引首先指向每个列键值的字节,然后在反向后的新数据上进行索引。例如,索引列键值为2011则反向转换为1102,9527反向为7259,显然经过反向处理的有序数据变得比较随机了,这样得到的索引树就比较对称,从而提高表的查询性能。
但是方向键索引也有局限性:如果在查询条件中有between、<、>等,其方向键索引无法使用,将执行全表扫描;只有对反向键索引列进行=的比较操作时,其反向键才会得到使用。
创建示例:
create index emp_job_reverse on emp(job) reverse tablespace test;
原索引为B树索引,修改为反向键索引:
alter index emp_deptno_index rebuild reverse;
4、基于函数的索引
用户在使用Oracle数据库时,最常遇到的问题之一就是他对字符大小写敏感。可以通过使用Oracle字符串函数对其进行转换,然后再进行检查。但是,使用这样的查询时,用户不是基于表中存储的记录进行搜索的,即如果搜索的值不存在表中,那么它就一定也不会在索引中,所以即使在列上建立索引,Oracle也会被迫执行全表扫描,并为所遇到的个行进行函数运算。为了解决这个问题,Oracle提供了一种新的索引类型--基于函数的索引,它也是常规B树索引,但它存放的数据是由表中的数据应用函数后所得到的,而不是直接存放表中的数据本身。
示例:
create index emo_job_fun on enp(lower(job));
5、修改索引
修改索引一般是通过alter index语句来完成。在表建立索引后,随着对表不断进行更新、插入和删除操作,索引中会产生越来越多的存储碎片,这将对索引的工作效率产生负面影响,这时可以采取两种方式来清楚碎片,重建索引或合并索引。
alter index emp_deptno_index coalesce deallocate unused; ------------索引碎片整理(coalesce)收回未用到的空间(deallocate unused);
假设在操作前,B树索引的前两个叶子块分别有70%和30%的空闲空间,合并索引后,可以将他们的数据合并到一个索引叶子块中。
消除索引碎片的另一个方式是重建索引,重建索引可以使用ALTER INDEX INDEX_NAME REBUILD,重建操作不仅可以消除存储碎片,还可以改变索引的存储表空间,然后再删除原理的索引。
示例:
alter index emp_deptno_index rebuild tablespace test ;------重建索引并指定表空间
6、删除索引
删除索引使用DROP INDEX INDEX_NAME,需要删除某个索引的情况主要有以下几种:
a)如果移动了表中的数据,导致索引中包含过多的存储碎片,此时需要删除并重建索引。
b)通过一段时间的监视,发现很少有查询会使用到该索引。
c)该索引不再需要时应该删除索引,以释放其所占用的空间。
索引被删除后,它所占用的空间都将返回给包含它的表空间,并可以被表空间中的其他对象使用。如果索引时定义约束时由Oracle系统自动建立的,则必须禁用或者删除约束本身,另外在删除一个表时,Oracle也会删除所有与表有关的索引。
关于索引最后需要注意一点,虽然一个表可以用于很多索引,但是表中的索引数据越多,维护索引的成本就越大,每当向表中插入删除更新一条记录时,Oracle都必须对该表的所有索引进行更新。因此,用户还需要在表的查询速度和更新速度之间找到一个合适的平衡点,也就是说根据表的实际情况限制在表中创建索引的数量。
7、显示索引的信息
select index_name,index_type from dba_indexes where owner='SCOTT'; ---查看用户下索引的信息
select column_name,column_length from user_ind_columns where index_name='EMP_DEPTNO_INDEX';---查看索引的表的列信息
select tablespace_name,segment_type,bytes from user_segments where segment_name='EMP_DEPTNO_INDEX'; ----查看索引段的信息
select column_expression from user_ind_expressions where index_name='EMP_JOB_FUN'; ----查看基于函数的索引信息
- ORACLE学习笔记 索引和约束
/*** 约束 ***/ * 如果某个约束只作用于单独的字段,即可以在字段级定义约束,也可以在表级定义约 束,但如果某个约束作用于多个字段, 必须在表级定义约束* 在定义约束时可以通过CONSTRA ...
- Oracle学习【索引及触发器】
索引B_Tree结构 请参照 响应图例 索引是一种允许直接访问数据表中某一数据行的树形结构,为了提高查询效率而引入,是独立于表的对象,可以存放在与表不同的表空间中.索引记录中存有索引关键字和指向表中数 ...
- oracle提高之索引学习
一. 索引介绍 1.1 索引的创建 语法 : CREATE UNIUQE | BITMAP INDEX <schema>.<index_name> ON <schema ...
- 【Oracle学习笔记】索引
1 简介 1)索引是数据库对象之一,用于加快数据的检索,类似于书籍的索引.在数据库中索引可以减少数据库程序查询结果时需要读取的数据量,类似于在书籍中我们利用索引可以不用翻阅整本书即可找到想要的信息. ...
- Oracle学习笔记—数据字典和常用命令(转载)
转载自: oracle常用数据字典和SQL语句总结 Oracle常用命令大全(很有用,做笔记) 一.Oracle数据字典 数据字典是Oracle存放有关数据库信息的地方,其用途是用来描述数据的.比如一 ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- Oracle Database 11g Express Editon介绍及安装
一.Oracle Database 11g Express版本介绍 公司项目开发中,使用的数据库是Oracle 10g和MySQL 5.5,最新因为开发需要,需要从后台读取一些数据.使用的客户端是PL ...
- Oracle学习线路
出自huyangg的博客,地址是:oracle学习路线图 1.sql.pl/sql(网上有很多的视频,可以做一个简单的入手,然后看几本书,多做实验) 作为oracle的基本功,需要大家对sql和 ...
- Oracle学习指南
Oracle学习指南 你走的那天,我决定不落泪,迎着风撑着眼帘用力不眨眼 创建数据库.创建用户.创建表空间.创建表.插入数据..... 1.用系统用户登录,任选系统用户 代码: >>sql ...
- docker~学习笔记索引
回到占占推荐博客索引 使用docker也有段时间了,写了不少文章与总结,下面把它整理个目录出来,方便大家去学习与检索! docker~学习笔记索引 docker~linux下的部署和基本命令(2017 ...
随机推荐
- net core api上传下载大文件 413、400错误 IIS服务器
1.背景 上传文件时,如果文件太大(一般指超过30M的文件)会报错,报错原因如下 IIS服务器:限制大文件上传,报413错误码 net core api项目:限制大文件上传,报400错误码 2.首先 ...
- 【6】java之数组的定义和使用
一.数组的定义与使用 1.1 数组的基本概念 数组指的就是一组相关变量的集合. 数组的定义: 声明并开辟数组 数据类型 数组名称 [] = new 数据类型[长度]: 数据类型 [] 数组名称 = n ...
- 在grafana中使用不同的数据源及插件安装
一.postgresql作为数据源 现在PG的版本是10.5(10+) 加入datasource 时只能指定一个数据库,对于监控来说可使用默认数据库postgres! 可以方便地作趋势图以及使用tab ...
- postman连接mysql数据库
转载:https://www.cnblogs.com/pengxiaojie/p/13495237.html 1.安装 2.启动服务 3.执行sql语句 安装: 想要postman连接mysql,需要 ...
- UniApp学习-多端兼容 & 跨域
多端兼容配置 标签 <!-- 一般标签 --> body ---- page div,ul, li, table,tr,td ---- view span,b,i,font ---- te ...
- Python 获取磁盘使用
import psutil def get_disk_info(): content = "" for disk in psutil.disk_partitions(): if ' ...
- python中周日历与时间的相互转换
python中周日历与时间的相互转换 周日历(ISO国际标准)介绍 在线周日历(2022年) 基本介绍 在开发过程中,有些汇总咨询需要以周为单位统计,所以介绍下如何进行相互转换. 使用datetime ...
- Ping命令的基本使用
一.Ping命令的基本使用 在网络中 ping 是一个十分强大的 TCP/IP 工具.我们通常会用它来直接 ping ip 地址,来测试网络的连通情况.它的作用主要为: 1.用来检测网络的连通情况和分 ...
- Windows2016安装.NetFramework 3.5
Windows2016安装.NetFramework 3.5 Windows2016服务器默认安装的是 .Net 4.6.2版本,但是有时候我们经常会需要用到.Net 3.5版本.以下介绍的是在线和离 ...
- 推荐一个json直接导出Excel的网站
https://wejson.cn/json2excel/