摘要:本文章先描述了经常使用的索引,并针对B-tree和Psort两种索引具体介绍,下面给出索引的利与弊。除了索引,还介绍了分区、PCK等其余查询提速的手段。最后给出各类索引和调优手段的使用场景。
本文分享自华为云社区《DWS 索引的正确“打开姿式”》,原文做者:hoholy 。数据库
索引能干什么呢,一言以蔽之:查询加速。常见的索引有下面几种:数据结构
1. 经常使用索引介绍
1.1 B-btree索引
B-tree存储结构示意以下:oop
- B-tree是平衡树,有序存储索引KEY值和TID;
- 对于索引上的过滤条件,经过KEY快速找到对应的叶子节点,而后再经过TID找到实际记录;
- 索引中的数据以非递减的顺序存储(页之间以及页内都是这种顺序),同级的数据页由双向链表链接;
- 支持单列索引和复合(多列)索引,多列复合索引适用于多列组合查询,B-tree索引对于查询条件的顺序有要求;
- B-tree索引能够处理等值和范围查询;
- 索引页面不存储事务信息;
在数据库里面举个例子,如何建立B-tree索引:性能
1.2 Psort索引
Psort索引数据结构示意以下图所示:优化
- Psort索引自己是个列存表,包含索引列和tid,在索引列上局部排序,利用MIN/MAX块过滤加速TID获取;
- Psort索引自己有可见性,但删除、更新数据不会做用到Psort索引;
- Psort索引更适合作范围过滤,点查询速度较差;
- 批量导入场景下有效,对于单条导入无效;
横向对比B-tree、Psort以下:url
1.3 特殊索引
-
表达式索引
好比对于查询“select * from test1 where lower(col1) = ‘value’;”能够创建在Lower表达式之上的索引“create index on test1(lower(col1));”,后续对于相似在lower(col1)表达式上的过滤条件,就能够直接使用这个索引加速,对于其余表达式该索引不会对查询生效。但须要注意的是:索引表达式的维护代价较为昂贵,由于在每个行被插入或更新时都得为它从新计算相应的表达式。spa
-
部分索引
好比建立一个部分索引“create index idx2 on test1(ip) where not (ip > ’10.185.178.100’ and ip < ’10.185.178.200’);”,使用该缩影加速的典型查询是这样“select * from test1 where ip = ’10.185.178.150’”,可是对于查询“select * from test1 where ip = ’10.185.178.50’”就不能使用该索引。部分索引用来减小索引的大小,排除掉查询不感兴趣的数据,同时能够加速索引的检索效率..net
-
惟一索引
(1)只有B-tree索引支持惟一索引;3d
(2)当一个索引被声明为惟一时,索引中不容许多个表行具备相同的索引值;日志
(3)空值被视为不相同,一个多列惟一索引将会拒绝在全部索引列上具备相同组合值的表行;
(4)对于主键列会自动建立一个惟一索引;
(5)惟一性检查会影响索引插入性能;
1.4 索引的利与弊
索引的优势以下:
- 点查询提速显著,直接定位到须要的位置,减小无效IO;
- 多条件组合查询,过滤大量数据,缩小扫描范围;
- 利用倒排索引加速全文检索;
- 利用等值条件索引查询速度快的优点,结合nestloop提升多表join效率;
- 提供主键和惟一性约束,知足业务须要;
- 利用btree索引自然有序的特色,优化查询计划;
索引的缺点以下:
- 索引页面占用额外空间,致使必定的磁盘膨胀;
- 每次数据导入同时须要更新索引,影响导入性能;
- 索引页面没有可见性,存在垃圾数据,须要按期清理;
- 索引扫描性能并不老是比顺序扫描性能更好,一旦优化器判断有误,可能致使查询性能反向劣化;
- 索引须要记录XLOG,增长日志量;
- 每一个索引至少一个文件,增长备份恢复、扩容等操做的代价;
鉴于索引的使用是一把双刃剑,建立索引要谨慎,只给有须要的列建立,不能过滤大量数据的条件列不要建立索引。除了索引能够优化查询效率,存储层还有没有其余优化手段呢?下面给你们再介绍几种DWS查询提速的手段。
2. DWS查询提速
2.1 分区
分区是最经常使用的提速手段之一,并且效果很好,推荐你们结合场景多多使用。
- 目前支持的分区是range分区,分区支持merge、split、exchange等操做;
- 在时间维度或者空间维度等具备必定数据规律的列上建立分区,分区列上的过滤条件会先作分区剪枝,减小物理扫描量;
- 相比较索引,分区直接把原始数据物理划分,一旦分区剪枝生效,会极大的减小IO;
- 使用分区和使用索引并不冲突,能够给分区建立索引;
使用分区的注意事项以下:
- 分区对于导入的影响是增长内存使用(内存不足时会下盘),但不产生额外的磁盘占用;
- 使用分区必定要注意分区列的选择和分区数量的控制,分区过多会致使小文件问题,分区数量建议最多不超过1600个;
- 分区剪枝适合范围查询,对于点查询效率提高有限;
下面举个例子,分别建立一样数据类型的分区表和非分区表,导入相同的数据640万条,用一样的查询会看到分区剪枝对性能提升了7倍多,准备数据:
分区和非分区查询耗时对比,其中test1是分区表,test2是非分区表,test1的查询scan耗时6ms,test2的查询scan耗时46ms,差距7倍还多:
2.2 PCK(partial cluster key)
PCK的本质就是经过排序提高查询过滤的效率,建立表时指定PCK列,该列上的数据会局部排序,有序的数据带来更好的数据聚簇性,每一个数据块的min/max等稀疏索引就能更好的发挥做用,粗过滤掉大量的数据,提高IO效率,默认状况下420万行数据局部排序。
注意事项以下:
- 只有列存表支持PCK,局部排序对每次导入的批量数据生效,不会作全排序;
- PCK更适用于范围查询,点查场景下配套使用PCK和索引能够达到最佳效果;
- 带PCK导入由于排序的缘由会使用更多的内存,影响导入速度,须要权衡导入和查询性能;
举个例子,对于查询select * from tab where col > 65,若是不使用PCK,极可能一个CU都没法过滤掉,但若是使用了PCK,下图所示的5个CU就能过滤掉一半还多,提高查询性能至少50%:
再用上面分区的那组数据横向对比PCK的性能表现:
(1)列存表,非分区,无PCK,scan耗时46ms
(2)列存表,非分区,有PCK,scan耗时1.7ms
(3)列存表,有PCK,再建立btree索引,scan耗时0.1ms
PCK结合索引,能够将相似这种点查的性能提高100倍以上。
2.3 智能过滤
列存表数据从文件读出来,到反馈给执行层,中间会智能识别自动多层过滤,对用户彻底透明,以下图所示:
3. 索引使用场景推荐