一:从索引的特性推导出它的三大特性
1.索引的层级:加入给id这个字段建立了索引。索引有层级,最底下这一层L层:L1、L2、L3...如L1存的是id1~id10,L2存的是id11~id20。以及类推。当L层出现了大于1个L1这样的单元时,就需要有一个管理层B1。值得注意的是,L层存的是值和伪列(用来记录行号的rowId),而往上的层级只是记录一个索引,并不存储值。
以此类推,当出现了不止一个B1的单元时,就需要有更高一层的R来管理。这样建立起来的层级数量就是每次sql查询时的逻辑读(consistent gets)的数量。
如果在同一个逻辑读的数量,那么即便它们记录的数量级有一定差距,sql执行速度也不会相差多少。而一旦逻辑读的数量出现差异,sql执行也会差异很大。
由此引出索引的第一个特性:层级不高。即便数量差异巨大,最终反映在逻辑读的层级差异也就是几层而已。
关于这点有一个常见的相关应用,就是分区表。当一个表设计成分区表后,sql没有用分区字段进行过滤,这个时候的查询效率会很低。因为分区表建立的索引是local,假设每块分区的逻辑读比不分区时少1,算上分区的数量,它的执行效率也就慢多了。那么解决办法:1分区字段进行过滤;2建立全局的索引
2 .索引的有序性:和(1.)提到的相关,L1是按照id1 id2...到id10的顺序存的,而L2紧接着L1的最后一个值id10,也就是id11的值开始存储。按照此规律,最后一个id值,自然就存储在最后一个L块的最后一个位置了。
因此这个原理,查询min(id)或者max(id)的效率是相当惊人的,因为它能直接定位了。这一点就是索引的有序性
3索引是存储值和伪列的:这隐藏的意思是索引不能存储空值,那既然索引并不存储空值,如果查询条件涵盖空值的话就无法走索引了。那么,select * from employ em 就是不走索引的,而想让它走索引就要加上条件‘ where em.id is not null’。
二:其余零星记住的散点
1. 假如创建了这两个索引Index_1(cstNo,cstNm),Index_2(cstNo,cstNm,Score),那么Index_1其实是冗余索引,应该删除。索引本身占用内存开销,不需要的应该删除。cstNo,cstNm这两个字段在Index_2中都存在,而且顺序一致,那Index_1就是冗余索引。
2前导列的应用:英文取自https://blog.csdn.net/iteye_13254/article/details/81678199
leading portion of an index is a set of one or more columns that were specified first and consecutively in the list of columns in the CREATE INDEX statement that created the index. Consider this CREATE INDEX statement:
CREATE INDEX comp_ind ON table1(x, y, z);
- x, xy, and xyz combinations of columns are leading portions of the index (x,xy,和xyz列组合都是索引的前导列)
- yz, y, and z combinations of columns are not leading portions of the inde(yz, y, z列组合则不是索引的前导列 )
由此看出,排在前面的字段本身,及它和其他字段组合成的列组合就是前导列。
据说前导列的排序顺序应按照高选择性原则,就是不重复数据越多(能查询出来的不同数据越多的字段)放前面。结合索引层级的原理,非重复数据越多,则能建立越多的索引块,定位效果越好,自然效率高。反之如果建立索引的字段重复值很多,那意味着会查询出很多数据,那索引的意义就大大折扣,甚至Oracle宁愿选择全表扫描了。
3其余的回顾后再补充