3 indexes and index-organized tables
索引总是建在table or table cluster上,可以减少磁盘i/o,提高数据访问速度。如果一个heap-organized表没有索引,那么查数据就一定会全表扫描。
如下情况可考虑使用索引: 1。索引列被经常查询,返回相对数目较少的纪录。2。作为子表,索引列有完整性约束。如果主表主健被更新??,子表merge到主表,或者从主表中删除时,在该列上建立索引可以避免一个全表锁。3。需要在该表上建立唯一健约束,并且你想手动指定索引和相关参数。
在一个表上建立许多索引,会降低DML性能,因为数据库需要维护和更新索引。
可用/不可用:不可用的索引(unusable)不被dml操作维护,且被优化器忽略。当把一个索引变成不可用时,数据库会drop掉该索引段。
可见/不可见:(invisible)被dml操作维护,被优化器忽略。
组合索引的列顺序很重要。当select语句中where提到了所有列,或者是前几列的时候,组合索引会派上用场。包括所有列,第一列,第一二列,第一二三列,等等。
索引分唯一索引和不唯一索引。唯一索引就是在unique key上建立的,可以想象索引值是按照key值进行排序的,不唯一索引则是key不是unique,所以索引值是按照key和rowid排列。
索引类型: b树索引:index-organized table(数据本身就是索引),reverse key indexes, descending indexes, b-tree cluster indexes . 位图索引:b树索引是指向一行,而位图索引指向多行。 function-based indexes application domain indexes
b树索引:将一组有序值分成段,适合精确匹配和范围搜索。
b树索引有两种数据块,分支块(共搜索),和叶子块(存值)。 b树索引是平衡的,因为所有的叶子节点都在同样的高度。每个叶子节点包含索引列的值,比如department_id=20,和一个相应的rowid指向存放该行数据的数据块。
index scan,一班需要n次i/o来找到叶子节点,n就是b树的高度。然后再用一次i/o去取得数据块存储的完整一行数据。
full index scan依序的读取整个index,比如 select department_id, last_name, salary from employees where salary > 5000 order by department_id, last_name; 假设这三个是一个组合索引,那么oracle就会进行full index scan,排序的读入数据,然后对salary进行过滤。这种扫描会比扫描employees表少很多数据,只需要对索引本身进行扫描,而不需要访问实际存储数据。
fast full index scan: a full index scan,但数据库不需要按序的读取index block。比如select last_name, salary from employees; 如果这两列是一个组合索引,则只需要一个fast full index scan就可以取到所需数据。
index range scan: 是一个有序的index scan, 且有如下特点:
1。 索引中的第一列或者前几列在where语句中,比如select * from employees where last_name like 'A%'; lastname是索引列,并且在where语句中。
2。index key所对应的真实数据有0,1 或更多行。对于Austin这个lastname, 有两个rowid和它相关联。
where中可以是单边的,也可以是双边的,10
unique scan.和index key所对应的真实数据要么有,要么没有, 在where语句中用了一个unique key中的所有列,并且是="号时,会使用该索引。" employees employee_id="5;"
index skip scan. 适用于where条件中没有索引健的第一列,且第一列的distinct value数量较少,而其余列的数量较多的情况。
比如select , 并且有索引(cust_gender, cust_email),cust_gender只有两个值male, female。 那么此时上述语句就会被翻译成 union all select * from sh.customers where cust_gender="M" and cust_email="Abbey@company.com" ;
索引的集群因子:index clustering factor. 对于该索引,邻近的index叶子节点,是否指向同一个数据块。衡量了对某一个索引来说, 扫面全表时的i o次数。
其实就是,这个表的实际存储情况,是否适合于使用该索引。如果employees表存储的时候是按照name升序存储的,那么在name列上建立一个索引后,很显然,该索引依序访问数据的时候,访问的数据块会较少。如果在id列上有一个索引,那么该索引依id序访问数据的时候,i o会比较多。 值越高,数据越无序,i o数越多。索引的入口指向随机的data block,因此数据库需要不断的读取整个数据块来取得索引指向的数据。 值越低,i o数越少。一段范围内的索引指向同一个数据块。
这个因子和索引扫描相关:1。数据库是否使用该索引来做大范围的扫描;2。对该索引来说,整个表的组织程度;3。如果行必须根据索引健排序,是否应该使用index-organized table, partitioning, or table cluster.
ALL_INDEXES表中可以查到这个因子数。
reverse key indexes: 反向索引是B*Tree索引的一个分支,它的设计是为了运用在某些特定的环境下的。Oracle推出它的主要目的就是为了降低在并行服务器(Oracle Parallel Server)环境下索引叶块的争用。
当B*Tree索引中有一列是由递增的序列号产生的话,那么这些索引信息基本上分布在同一个叶块,当用户修改或访问 相似的列时,索引块很容易产生争用。反向索引中的索引码将会被分布到各个索引块中,减少了争用。
反向索引反转了索引码中每列的字节. 反向索引就是将正常的键值头尾调换后再进行存储,比如原值是“1234”,将会以“4321”形式进行存储,这样做可以高效地打散正常的索引键值在索引叶块中的分布位置。
1. 反向索引应用场合
1)发现索引叶块成为热点块时使用 通常,使用数据时(常见于批量插入操作)都比较集中在一个连续的数据范围内,那么在使用正常的索引时就很容易发生索引叶子块过热的现象,严重时将会导致系统性能下降。
2)在RAC环境中使用 当RAC环境中几个节点访问数据的特点是集中和密集,索引热点块发生的几率就会很高。如果系统对范围检索要求不是很高的情况下可以考虑使用反向索引技术来提高系统的性能。因此该技术多见于RAC环境,它可以显著的降低索引块的争用。
2.使用反向索引的优点 最大的优点莫过于降低索引叶子块的争用,减少热点块,提高系统性能。
3.使用反向索引的缺点 由于反向索引结构自身的特点,如果系统中经常使用范围扫描进行读取数据的话(例如在where子句中使用“between and”语句或比较运算符“>”“<”等),那么反向索引将不适用,因为此时会出现大量的全表扫描的现象,反而会降低系统的性能。
4.通过一个小实验简单演示一下反向索引的创建及修改
1)创建一个实验表T sec@ora10g> create table t (x int); Table created.
2)创建反向索引,在正常创建索引的语句后面简单的加上“reverse”关键字即可。 sec@ora10g> create index idx_t on t(x) reverse; Index created.
3)使用user_indexes视图查看一下索引的类型,“NORMAL/REV”表示该索引类型为反向索引。 sec@ora10g> col TABLE_NAME for a10
sec@ora10g> col INDEX_NAME for a10
sec@ora10g> select table_name, index_name, index_type from user_indexes where table_name = 'T'; TABLE_NAME INDEX_NAME INDEX_TYPE ---------- ---------- --------------- T IDX_T NORMAL/REV
4)修改反向索引为正常索引当反向索引无法满足我们的需求的时候,我们可能会考虑修改反向索引为正常的索引结构。除了删除索引重新创建这种方法外,可以直接使用noreverse选项重新rebuild索引。
sec@ora10g> alter index idx_t rebuild noreverse; Index altered.
5)最后确认一下,该索引已经修改为正常的索引。 sec@ora10g> select table_name, index_name, index_type from user_indexes where table_name = 'T';
TABLE_NAME INDEX_NAME INDEX_TYPE ---------- ---------- --------------- T IDX_T NORMAL
升序索引和降序索引:默认情况是升序,字符按照二进制排,数字是从小到大,日期从早到晚。比如department_id=1在平衡树的左边,最大值在树的右侧。可指定倒序,当一个查询要倒序的时候是有用的。
索引健压缩:对复合索引。我们可以将重复的部分抽出作为共同的索引,从而减少空间,但是空间是以CPU的计算为代价的。
比如复合索引: FH_index ( owner,object_type,object_name ) 以下是一个索引块 FH_index的伪代码 TEST TABLE T1 TEST TABLE T2 TEST TABLE T3 TEST TABLE T4 TEST TABLE T5 那么可以压缩为: (压缩第一个字段) TEST TABLE T1 TABLE T2 TABLE T3 TABLE T4 TABLE T5 或 TEST TABLE (压缩第1,2个字段) T1 T2 T3 T4 T5
bitmap indexes:b树每个索引都指向一行,位图索引中每个索引指向多行数据。位图索引主要是在数据仓库中使用:1。索引列的cardinality较低(distinct values较少)。2。索引表要么只读,要么不会有dml语句对其作重大改变。位图中的每一位都对应一个rowid。如果一个位被设置了,那么该rowid所指向的行包含了索引健值。一个映射函数会把位的位置转换成实际的rowid,因此该索引提供了和b树索引相当的功能。如果某一行的数据中的索引列内容被更新了,那么数据库会锁住索引健值,比如male, female,也就是很多行,而不仅仅是那个指向那行的位。所以该索引不适用于OLTP应用。位图索引尤其在处理count时会比较高效,只需要计算在位图中1的个数。
bitmap join indexes:为两个或多个表的连接,建立的位图索引。
比如对于查询
select count(*) from employees, jobs where employees.job_id = jobs.job_id and jobs.job_title = 'Accountant'; 可以建立索引
CREATE BITMAP INDEX employee_bm_ind ON employees (jobs.job_title) FROM employees, jobs WHERE employees.job_id = jobs.job_id;
就是对表employees建立索引,索引列是
job_title. jobs.job_title employees.rowid
Accountant XXXXXXXXXXXXXXX
Accountant XXXXXXXXXXXXXXX
Accounting Manager XXXXXXXXXXXXXXX
Administration Assistant XXXXXXXXXXXXXXX 在数据仓库中较常用。
Bitmap 存储结构:oracle数据库用b数索引结构来存储位图信息。 每个单独的位图信息(比如对male, femail,分别会有一个位图序列)存储在叶子节点中。
比如对jobs.job_title建立了位图索引,那么每一个叶子节点中包含信息:
1。Job title
2.对应的一组rowid的最小rowid和最大rowid
3.对该组rowid的位图序列
一个位图索引中的数据会存放在一个段中。
Function-based index:函数既可以使数学运算,也可以包含sql, plsql等。只有函数在查询中包含时,数据库才会使用该索引。
Application domain indexes: oracle提供的可扩展的索引机制。可以对复杂数据类型,例如文档,图像等,可以使用定制的索引技术。
Index-Organized Table
是一个标,存储在变形的b树索引结构中。
在一个堆组织的表中,行在它们合适的数据块中插入。在一个索引组织的表中,行被插入到索引中。索引就是数据,数据就是索引。
索引组织表提供了基于主健(或主健的前几列)对表的快速访问。适用于OLAP应用。
堆组织表和索引组织表的对比:
堆组织表:
1.rowid可以唯一的标识一行。主健约束可以被定义。
2. ROWID这个伪列上存的是物理rowid,可以建立二级索引。
3.每行可以通过rowid直接访问。
4.顺序的全表扫描可以依某种序返回所有行。
5.可以和其他表一起存储在table cluster中
6.可以包含LONG数据类型和LOB数据类型作为列类型
7.可以包含虚拟列(只有关系型堆表支持)
索引组织表:
1.主健值唯一标识了一行。主健约束必须被定义。
2.ROWID这个伪列上存的是逻辑rowid,可以建立二级索引。
3.每行可以通过主健访问。
4. 一个全索引扫描full index scan或者快速全索引扫描可以依序返回所有行。
5. 不能存储在table cluster中。
6. 可以包含LOB列,不能包含LONG列。
7. 不能包含虚拟列。
其实一个索引组织表就是把表的所有行数据存储在索引树的叶子节点上,不需要rowid。对一个堆组织表来说,它的索引数存储主健值,和相应行数据的rowid。它做索引扫描的时候,先扫描索引,得到rowid,然后通过rowid去访问数据,它的i/o是索引组织表的两倍。
Row overflow area: 因为叶子节点存储的值可能占用空间很大,所以可能需要额外的空间来存放值,这样整行数据就被切割中两部分,类似于堆组织表的索引,一部分存放主健值,和一个rowid,指向overflow部分,这些内容在索引段中。第二部分存放的就是第一部分没有存的值,放在overflow段中。
Secondary Index:
二级索引就是在索引组织表上建立的索引。它是一个独立的schema object,和索组织表的存储分开。
逻辑rowid:在索引组织表中用逻辑rowid,它是对表主健的编码标识,长度依赖于主健的长度。二级索引就是用逻辑rowid去定位数据。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11903161/viewspace-675459/ ,如需转载,请注明出处,否则将追究法律责任。