WHERE中有很多IN判断怎么提速?
一、WHERE中有很多IN判断怎么提速
WHERE 中的 IN 是要过滤出某字段值包含在给定枚举值集合中的记录,比如:查出某几个城市的客户、某些类型的订单等等。
数据库做 IN 过滤时,要用字段值和值集合的成员作比较计算。若采用顺序查找,要比较 1 到 n 次(n 是值集合大小)。即使在值集合有序的情况下用二分法查找,也要比较数次。数据量较大时比较次数会非常多,IN 的速度就会很慢,而且值集合越大速度越慢。
如果在过滤时不再做比较计算,性能就能得到大幅提高!
首先,确定 IN 可能取值的列表。可能值通常不会太多,一般都保存在一个选项表中。如果没有现成的选项表,要遍历原数据得到所有可能值,保存成一个选项表。然后转换原数据,把 IN 字段值替换为选项表中对应记录的序号(位置),另存成一份新数据。
对替换后的新数据做 IN 判断时,先生成一个与选项表等长的布尔值集合,其第 i 个值由选项表的第 i 个成员是否在 IN 的值集合中决定,在就是 true,不在就是 false。
然后遍历新数据,用 IN 字段值(也就是选项表的序号)去取布尔值集合中的成员,是 true 就符合过滤条件,否则就不符合。
这种方法本质上是将“集合值比较”转换为“序号引用”,省去了比较计算,性能会大幅提升。而且计算时间和值集合大小无关,不会随着 IN 枚举值的增多而增加。
但是,SQL 不支持通过序号(位置)直接取集合中的成员,无法实现这种优化方法。
集算器 SPL 支持序号引用,可以很方便的实现这个优化方法。
1、 数据预处理,转换为序号。
=cs.run(dim1.pos@b(f1):f1),遍历原数据,使用 pos 函数查到原数据 f1 字段在选项表 dim1 中对应记录的序号,用这个序号代替原来的 f1 字段值,另存一份新数据。dim1 预先按照 f1 对应值排好序了,所以这里采用二分法查找,预处理的速度更快。
2、 对预处理好的新数据做 IN 过滤计算。
假设传入值集合为 arg_F1,生成布尔值集合的代码是:
b1=dim1.(arg_F1.contain@b(~)),arg_F1 有序,所以这里也是二分法查找。
然后就可以用新方法过滤新数据了:
=file(“T.ctx”).open().cursor(…;b1(f1) && …),用 f1 中的序号,直接去取布尔值集合中的成员,成员是 true 则满足过滤条件,否则就不满足。这时不需要再做比较计算,性能会大幅提高。
实测表明,在同等硬件环境下,用 SPL 实现的这种方案比 Spark 上的 SQL 快了上百倍。
延伸阅读:
二、联合索引 (a,b,c)
联合索引 (a,b,c) 实际建立了 (a)、(a,b)、(a,b,c) 三个索引。
我们可以将组合索引想成书的一级目录、二级目录、三级目录,如index(a,b,c),相当于a是一级目录,b是一级目录下的二级目录,c是二级目录下的三级目录。要使用某一目录,必须先使用其上级目录,一级目录除外。
联合索引的优势
1) 减少开销
建一个联合索引 (a,b,c) ,实际相当于建了 (a)、(a,b)、(a,b,c) 三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!
2)覆盖索引
对联合索引 (a,b,c),如果有如下 sql 的,
SELECT a,b,c from table where a=’xx’ and b = ‘xx’;
那么 MySQL 可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机 io 操作。减少 io 操作,特别是随机 io 其实是 DBA 主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。
3)效率高
索引列多,通过联合索引筛选出的数据越少。比如有 1000W 条数据的表,有如下SQL:
select col1,col2,col3 from table where col1=1 and col2=2 and col3=3;
复制
假设:假设每个条件可以筛选出 10% 的数据。
A. 如果只有单列索引,那么通过该索引能筛选出 1000W10%=100w 条数据,然后再回表从 100w 条数据中找到符合 col2=2 and col3= 3 的数据,然后再排序,再分页,以此类推(递归);B. 如果是(col1,col2,col3)联合索引,通过三列索引筛选出 1000w10% 10% *10%=1w,效率提升可想而知。
相关推荐HOT
更多>>
在 iPad 上运行 Windows 是什么体验?
一、在 iPad 上运行 Windows 是什么体验目前市面上有一些能够在 iPad 上运行 Windows 的应用程序,例如 Parallels Access、Splash较好、VMware ...详情>>
2023-10-14 19:14:27
vector, list, map等容器使用场合是什么?
一、vector, list, map等容器使用场合vector适用于对象简单,变化较小,并且频繁随机访问的场景。list适用经常进行插入和删除并且不经常随机访...详情>>
2023-10-14 14:59:11
分库分表的数据库和分布式数据库有什么区别?
一、分库分表的数据库和分布式数据库有什么区别分库分表的数据库:没有这种数据库,所谓分库分表,这是开发应用的程序员通过自己的代码、或者底...详情>>
2023-10-14 13:59:18
APP定制开发的难点有哪些?
一、APP定制开发的难点1、多平台适配不同的移动平台(如iOS和Android)具有不同的操作系统、开发语言和开发工具。在进行APP定制开发时,需要适...详情>>
2023-10-14 12:57:35