涉及知识:
1.索引的区别2.回表的优化
问题现象:语句非常简单,在预算-启用方案时,会进行查询的调用。当预算方案过多的时候,distinct的执行效率会显示降低。
select
distinct fromitems ,
ctllevels
from
tb_ctrlscheme
where
ctrlsys = 'erm'
问题分析:
这里的ctrlsys字段基本不具有筛选性。这里我们可以先看一下目前的执行计划,在ctrlsys字段上存在索引。
从目前的执行计划可以得知,虽然走了where条件的索引,但是由于不具备选择性,所以走了index fast full scan。这样走效率较低,并且还要回表进行查询。
这里我们需要说明几点索引的道理:
1.索引的价值在快速定位。索引不记录空值,B+树索引的优势在于矮而胖。也就是可以通过简单几层的树形查找,迅速找到目标数值。
2.索引本身是有序的。
3.不同的索引有不同的功效。比如:
函数索引:where条件中如果存在函数运算,则索引字段无法生效。可以通过建立函数索引的方式来提高速度。
位图索引:通过建立位图,通过与或非的预算,一次锁定多位,来进行匹配。适用于数量多,基数少的场景。如性别字段。
倒排索引:为了减少热块的竞争。比如100001 100002 100003,如果正向建立索引,查找较慢。而将数值反转,则可以快速通过尾号进行筛选。此时非常适合使用倒排索引。
组合索引:将需要的字段进行多列的组合。比如想要取消回表,则可以通过建立组合索引的方式,让select的字段不再回表查询。组合索引的列的选择以及列的顺序比较有讲究。一般选择等值条件作为首列,一般需要尽可能的减少索引跳跃扫描。
这里我们通过建立组合位图索引,来解决distinct带来的效率问题。
问题解决:
create bitmap index unfromitems on tb_ctrlscheme(fromitems,ctllevels);
复制代码
这里我们将distinct的两列都列入位图索引。
在进行匹配的时候,可以使用到位图索引的特性,快速定位重复值。将原来需要十几秒的SQL变为只需要1秒。因此问题得到解决。
同时删掉了原来where字段上面的索引,避免回表。有的时候,查询索引+回表的效率要低于全表扫描,因为全表扫描可以一次读多个块。
同时我们还需要注意,各种索引失效的场景以及优劣势。
位图索引的劣势在于,一次需要锁定多个数据行。如果该表经常进行增删操作的话,索引维护的成本比较大,容易造成锁等待。所以,要基于场合进行优化。
最终的执行计划如下: