大家好,今天给大家分享一个百度智能云GaiaDB在MySQL内核优化上的黑科技——如何让包含数十万个值的IN查询,从原来的20秒降到0.3秒!在生产环境中,通常很多业务场景会使用包含成千上万个取值的 IN 谓词进行数据过滤。然而当列表过大时,MySQL 的 range optimizer 容易因内存限制(由 range_optimizer_max_mem_size 控制)而失效,导致查询退化为全表扫描,严重影响性能。百度智能云GaiaDB 从 3.2.3.1 版本开始,支持将大 IN 列表自动转换为 IN 子查询,从根本上解决了这一瓶颈。摘要:大家好,今天给大家分享一个百度智能云GaiaDB在MySQL内核优化上的黑科技——如何让包含数十万个值的IN查询,从原来的20秒降到0.3秒!在生产环境中,通常很多业务场景会使用包含成千上万个取值的 IN 谓词进行数据过滤。然而当列表过大时,MySQL 的 r
传统 MySQL 的优化瓶颈
在处理形如:这样的 IN 列表时,若 column 有索引,MySQL 会尝试使用 range optimizer 将其转换为多个 OR 条件,并进一步尝试使用索引范围扫描。然而该过程存在两个明显短板:内存消耗大:优化过程需占用大量内存,一旦超出 range_optimizer_max_mem_size 即退化为全表扫描;索引选择不准确:当列表长度超过 eq_range_index_dive_limit 时,优化器无法通过 index dive 获取精确的数据分布信息,只能依赖简单的索引统计量,容易导致执行计划劣化。百度智能云GaiaDB 的解决方案:IN 列表转 IN 子查询
百度智能云GaiaDB 将 IN 列表改写为如下形式:该改写将 IN 列表转换为一个由表值构造器组成的非关联子查询,从而绕过 range optimizer 的内存限制,转而采用 semi-join 物化策略执行(由于临时表的数据量一般远小于外部表,因此会走 materialization-scan 模式),其流程如下:构造并物化临时表:将 IN 列表中的值构建为临时表;索引关联查询:从临时表中取一行数据,使用外表索引进行匹配;高效匹配输出:遍历临时表完成全部匹配。该方法不仅规避了 range optimizer 的内存瓶颈,还充分利用了索引,实现了与 range scan 同等级别甚至更优的查询效率。适用条件与参数设置
百度智能云GaiaDB 在以下条件下自动启用 IN 谓词转 IN 子查询:版本要求:GaiaDB 3.2.3.1 及以上;列表长度:IN 列表中元素数量 ≥ gaia_in_predicate_conversion_threshold;语法位置:IN 谓词位于 WHERE 或 ON 子句顶层,且仅通过 AND 连接;不支持场景:NOT IN 或无索引字段。使用方法
通过 gaia_in_predicate_conversion_threshold 参数控制该功能开启。示例
表结构:SQL语句:关闭当前特性的执行计划:打开当前特性的执行计划:性能测试
测试一:使用sysbench模型测试1.准备5000w数据:2.查询带10w个常量值的语句,k字段上有索引:3.结果对比:测试二:使用TPC-H数据集测试1.准备TPC-H 10GB标准测试数据集;2.询带10w个常量值的语句,l_partkey 字段上有索引:3.结果对比:
结论
百度智能云GaiaDB 通过将大 IN 列表智能转换为 IN 子查询,结合 semi-join 物化策略,有效克服了传统 MySQL 在处理大列表时的内存与优化限制。在实际测试中,查询性能提升显著,尤其适用于高并发、大数据量的在线业务场景。该功能无需业务改造,仅通过参数即可控制,是 百度智能云GaiaDB 在查询优化方面的重要增强。来源:科技深观察
