通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

WHERE中有很多IN判断怎么提速

WHERE 中的 IN 是要过滤出某字段值包含在给定枚举值集合中的记录,比如:查出某几个城市的客户、某些类型的订单等等。数据库做 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,效率提升可想而知。
相关文章