----------------------《海量数据库解决方案》读书笔记-----索引的选定准则----------
1.1不同类型表的索引应用准则
1.小型表
对小型表也应该创建索引:如果只是单一小型表的读取,有无索引影响不大,但是大多数情况是与其他表连接的情况下使用,索引对优化器的判断影响重大,这时将影响速度,必须创建索引。
小型表也可以考虑采用索引组织表(IOT)
2.数据无变化的大中型表(起参考作用)
特点:这种表中存储的数据具有较强的独立性,大部分情况下只读取其中满足条件的一部分,以大量查询为主,很少有数据更新。
索引创建:在没有索引的情况下,完成表的创建,然后一次创建好索引,可以考虑将参数PCTFREE设置为近似于0的值。
3.管理具体业务行为的大中型表。
特征:在查询中经常位于循环的外侧,并且随时间的推移数据量不断增加。
由于数据量不断增加,所以哪怕在索引的构成上稍微有些问题,都会在很大程度上导致数据查询范围的扩大。
数据量不断增加也就意味着我们不能忽视数据插入时的代价,过多的索引不仅会增加数据插入时的成本,而且在某种程序上也会增加对存储空间的需求。
通过构建最理想民的索引,实现以尽可能少的索引满足习可能多的数据读取要求。
4.存储用的大型表:
特点:数据不断增加的大表,读取非常少。
可以将这种表的PCTFREE设置为0。
由于这种表中使用主键也容易增加成本开销,所以在允许的情况下建议不要设置主键约束。
可以将时间较久不经常使用的数据存储在独立的分区中对其进行单独管理,从而减轻该表的整体负担。可以为每一个分区创建一个本地索引,而对于需要经常使用的分区可以为其创建较多的索引。
解决分区单独创建索引的方法:首先将本地索引的状设置为UNUSABLE,此时,数据库只完成了索引的定义,索引中并没有存储任何数据,对于使用附加性索引的分区可以通过执行索引重构操作,将索引的状态改变为USABLE。
从已经将索引状态设置为UNUSABLE的分区中读数据时经常会出现错误。为了避免此类错误,可以采用在FROM中指定特定分区名称的方法。即使不这样做,如果优化器通过使用分区键的查询条件就可以确定查询分区的话,则该问题也可以很容易地得到解决。
1.2离散度和损益分界点。
创建索引的目的是快速从整体集合中选择性地读取满足条件的一部分集合。
在查询条件有缩减查询范围的驱动查询条件,也有起检验作用的过滤查询条件。
把拥有最查询范围的条件作为驱动查询条件来使用。
一般情况对离散度低于10%-15%的查询构建索引,但是对于高于该离散度却可以局部范围扫描时也可以构建索引。
1.3索引合并和组合索引的比较
1.在允许的情况下,对具有较好离散度的列单独创建索引,这样可以提高该索引的使用弹性;
2.对于离散度较差的列,通过对多列进行合理的组合来创建组合索引。
如果很容易就能够分辨出查询条件的优劣,则只需要从中选择最好的一个作为驱动查询条件就可以了;但是如果很难分辨,则需要考虑让多个列相互组合来共同负责数据的读取任务,这就是所谓的索引合并(Index Merge).
只有当合并的索引具有相似的离散度时索引合并才比较有效
(个人理解:索引合并是单独的几个索引,在查询时同时(并非真正同时)读取的过程,区别于一般情况:索引1执行完,再执行索引2的情况)
在两个索引行数悬殊的情况下,通常只使用其中最好的一个索引来负责读取数据,而另外的索引只负责检验即可。
为了解决即使列的离散度不好也必须要创建索引的情况,需要创建组合索引(Concatenated Index),它与单一索引列的索引合并相比更能够提高数据的读取速度。
在查询条件中对索引列使用了等会比较时组合索引才能够有突出的表现。
1.4组合索引的特征。
当组合索引的第一个索引列(通常称为先导列)没有出现在查询条件中时,一般情况下该无法被使用。尽管可以使用“跳跃式索引扫描”,但是限制条件多,且效果不好。
创建组合索引涉及两个非常重要的方面:第一,基于什么样的列创建索引;第二,按照什么样的顺序创建索引。
对组合索引的执行速度影响最大的是使用非等值比较的查询条件。如果没有为索引的第一列使用“=”比较的查询条件,则即使为后面的列使用“=”比较的查询条件也仍然不能达到缩减查询范围的目的。
使用IN:
在使用组合索引时,不是所有的查询都在第一列使用等值条件,但是也不可能为所有的查询都重新建索引,所以可以使用IN将非等值查询转换为等值查询
在没有为组合索引的中间列赋予查询条件的情况下,如果随意使用了子查询则容易发生非常严重的性能问题。(这段没怎么读懂,把结论先摘出来)
对查询范围不构成直接影响的列的添加准则。
在为某个组合索引选定列时,首先应该考虑的是对直接缩减查询范围起着重要作用的列;其次,对附加性列是否会有利于提高执行效率等相关问题进行全面分析。
1.5组合索引中列序的决定准则
1阶段:是否经常使用?
2阶段:是否经常为列使用“=”比较查询条件?
3阶段:哪个列具有更好的离散度?
4阶段:经常按照何种顺序进行排序?
5阶段:何种列将作为附加性列被添加?
在1阶段,决定列序时不仅要考虑列在查询条件中使用与否,而且还要考虑跳跃式扫描能否被使用。
1.6索引的选定步骤
--这一小节基本上是对前面的总结,再加以例子说明,很实用,回头还可以再细细看看
1.全面搜集表的读取类型
2.选定索引列对象并调查其离散度。
3.为特殊读取类型选定索引。
4.检查聚簇。
5.组合索引的构成及索引的决定。
6.试验和测试
7.调查和修改相关应用程序
8.统一应用。
开发时无法收集到所到的读取类型,可以随着读取类型的不断出现而对索引进行连续不断的调整。
运行阶段读取类型的搜集方法:
使用工具,自动从应用程序代码中抽出SQL,或者是也可以使用从数据库的SQL共享池中抽出SQL。如果上面方法都不行,就只能从应用程序的人世难逢开口笑寻找被嵌套在其中的SQL了
1)从应用程序的代码中抽出SQL之后,将其瞧在专门用来分析的表中。
2)解析SQL-TRACE文件,获得SQL语句,执行计划,使用的索引,执行次数,查询范围等详细信息。
3) 从共享池中直接寻找SQL的方法非常简便,该方法的最大优点就是它不仅不受一般编程语言的旷,而且与解析TRACE文件的方法相比可以在较长的期间内使用。
只有在基于驱动查询条件创建索引的情况下,索引才具有其存在的价值。
索引最大的缺陷就是在使用它读取大范围数据时,会发生大量的随机读取,使得执行速度急剧下降。为了弥补这个缺陷,可以通过使用聚簇索引来有效地读取大范围数据。
为了实现分散I/O的目的,通常应当创建一个独立的索引表空间。