MySQL 'IN'大量值的运算符

  • 本文关键字:运算符 IN MySQL mysql
  • 更新时间 :
  • 英文 :


我正在观察奇怪的行为,我试图理解。

MySQL版本:5.7.33我有下面的查询:

select * from a_table where time>='2022-05-10' and guid in (102,512,11,35,623,6,21,673);

a_tabletime,guid上有主键,在guid上有索引
我上面写的查询有很好的性能,根据解释计划是using index condition; using where; using MRR

当我在in子句中增加value的数量时,性能会受到显著影响。

经过一些演练后,我能够得到一个粗略的数字。对于小于~14500的值,解释计划与上述相同。对于高于此值的数量,解释计划仅uses where,并且需要永远运行我的查询。

换句话说,例如,如果我在in子句中放入14,000个值,则解释计划如预期的那样有14,000行。但是,如果我在in子句中放入15,000个值,则解释有221200324行。整个表中都没有这么多行。

我正试图理解这种行为,并知道是否有任何方法来解决这个问题。

谢谢

阅读关于限制内存使用以优化范围

当您在IN()谓词中有一个大的值列表时,它会在查询优化步骤中使用更多的内存。在某些情况下,这被认为是一个问题,所以最近版本的MySQL设置了最大内存限制(默认为8MB)。

如果优化器发现它需要比限制更多的内存,那么在您的查询中没有其他条件可以用来优化,它放弃尝试优化,并诉诸于表扫描。我推断您的表统计数据实际上显示该表有~ 2.21亿行(尽管表统计数据是不准确的估计)。

我不能说我知道确切的公式来知道给定值列表需要多少内存,但是根据您观察到的行为,我们可以猜测平均每个项大约需要600字节,假设14k项可以工作,超过14k项就不能工作。

可以通过设置range_optimizer_max_mem_size = 0来关闭内存限制。这会造成内存使用过度的风险,但它避免了优化器"放弃"。在我的上一份工作中,我们在所有MySQL实例上设置了这个值,因为我们无法教育开发人员避免在他们的查询中创建巨大的值列表。

最新更新