索引管理¶
神通数据库的表是堆组织表,数据在堆页面没有顺序排列的要求,向堆组织表插入数据时,对写入的位置没有特定要求,可将其存放在新开辟的页面中,也可以存放在之前删除的元组空出来的空间上。这种形式的好处是堆组织的表结构比较简单,问题是无法使用一些常用的查询算法来查询数据,通常只能采用顺序扫描的方法,对整个堆进行扫描,即使SQL语句中像a=1这样的约束条件,顺序扫描没办法采取任何优化措施。
神通数据库通过引入索引以提高数据库的查询性能,索引对数据进行“预处理”,使之变成我们期望的组织结构,并将这种期望的组织结构与数据建立映射关系,类似于书籍的“目录”,建立“标题”和“页面”的映射关系,从而达到快速读取所需数据的效果。所以,索引本身是一种空间换时间的方法。
索引的性质¶
1.索引中不仅存储了与堆表数据的映射关系,同时也存储了索引列的值,也就是索引键值。一般情况下,我们会根据限定条件(如where a = 1)先在索引中找到对应键值(a = 1)的数据,然后根据映射关系再去堆表中拿取对应的行。如果查询的结果列就是索引列(如 select a from t where a = 1), 那么我们无需再去堆表中拿数据,降低了IO的开销。
2.索引中的数据都是排好序的,且排序的次序同索引列的顺序一致。
3.索引宽度可以理解为我们在查询时扫描索引树的宽度。我们知道对于等值查询(如 where a = 1)可以在索引中直接定位,但对于范围查询(where a >= 1)需要确定索引扫描的范围,所以我们在设计索引的时候希望索引扫描的范围尽量小,即索引宽度尽量窄。这里还有一点需要注意,单列索引情况下我们要明确(a=1)的范围一定不大于(a>=1),但不同列来说,我们需要比较不同列的选择率,选择率低的产生的索引宽度相对窄。
创建高效索引¶
一、基于规则的索引推荐
根据索引的性质,我们总结了构建高效索引的三个基本原则:
1.查询相关的索引行相邻或者相距足够近,这样可以最小化扫描索引片的宽度。
2.如果存在排序,排序列的顺序需要和索引列的顺序保持一致,可以去掉不必要的排序操作。
3.索引行包含查询语句中所有列,这样仅需要访问索引,避免了访问表的操作。
针对上述三条原则,我们认为创建高效的索引可遵循以下两个方向:
1.认为选择谓词比排序更重要
a.取出等值谓词列,作为索引的前导列,任意顺序皆可;
b.将选择性最好的范围谓词作为索引列的下一列,如果存在的话。这里选择性最好指的是对于最差的输入值有最低的选择率;
c.以正确的顺序添加order by列;
d.以任意顺序将select语句中其余的列添加至索引中。
2.认为排序更重要
a.取出等值谓词列,作为索引的前导列;
b.按照ORDER BY 的顺序添加ORDER BY列;
c.以任意顺序将SELECT语句其余的列添加至索引中。
注解
虽然索引能够提升数据库的查询性能,但是当对表中的数据进行更新时,同时需要对索引的结构进行更新,因此更适合在经常查询而很少更新的表上建立索引。
需要注意的是并不是索引列越多越好,索引的组织需要一定的存储开销。因此不建议对很少使用的列建立索引。
二、基于代价的索引推荐
上述描述基于规则的索引推荐依赖用户对数据库的深入了解,如果数据库自动给出推荐的索引,将会大大节省用户的时间。
基于此,我们开发了索引推荐功能:索引推荐函数 及 索引推荐语法
索引推荐是一种自动为给定SQL语句推荐合适索引的技术。在数据库优化阶段,索引推荐功能扮演着关键角色,下面将介绍索引推荐功能的技术原理:
1.依据SQL找出可以创建索引的列,如 select * from t where a =1 and b=2; 可以确定a,b两列可以作为索引推荐的候选项。
2.对单列的候选项进行排列组合,形成最终的组合候选项,如a,b列可以形成如下后选项[a,b,ab,ba]。
3.优化阶段,优化器会在候选项中找出代价最低的索引组合。
注解
1.两种推荐功能区别: 索引推荐函数 更适用于对 一组sql 进行索引推荐; 索引推荐语法 仅适用于对 一条sql 进行索引推荐。
2.索引推荐函数需要考虑的性能问题:在生成组合索引候选项时,会涉及到单个索引列多少的问题,这里需要注意的是组合索引列并不是越多越好。从索引组织、索引大小以及查询效率等综合因素考虑,过多的索引列并不是必要的,因此建议使用索引推荐函数时尽量采用较少的组合索引列达到性能较优的目的。
3.推荐出来的索引,只是内部估算的结果,未必是最优的。只要按照推荐的索引创建后的执行计划,比创建索引前更优即可。
4.由于 索引推荐函数 是对一组sql进行处理,推荐结果更需要考虑第二点,所以函数推荐索引据此做出了一些优化(采用贪心算法)。因此对于单独的一条sql,两种方法推荐索引的结果可能不一致,这是正常的。