MySQL 'IN' 大量值的运算符
MySQL 'IN' operator on large number of values
我正在观察我试图理解的奇怪行为。
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_table
在 time,guid
上有主键,在 guid
上有索引
我上面写的查询有很好的性能,根据解释计划是 using index condition; using where; using MRR
随着我在 in
子句中增加值的数量,性能受到显着影响。
经过一些枯燥的 运行s,我能够得到一个粗略的数字。对于小于 ~14500 的值,解释计划与上面相同。对于高于此值的数量,仅解释计划 uses where
并且 运行 我的查询需要很长时间。
换句话说,例如,如果我在 in
子句中放入 14,000 个值,解释计划将按预期有 14,000 行。但是,如果我在我的 in
子句中放入 15,000 个值,则解释有 221200324 行。我整个 table 中甚至没有这么多行。
我正在尝试了解此行为并想知道是否有任何方法可以解决此问题。
谢谢
了解 Limiting Memory Use for Range Optimization。
当 IN()
谓词中有大量值时,它会在查询优化步骤中使用更多内存。在某些情况下,这被认为是一个问题,因此 MySQL 的最新版本设置了最大内存限制(默认为 8MB)。
如果优化器发现它需要的内存超过限制,则查询中没有其他条件可用于优化,它会放弃尝试优化,并求助于 table-scan。我推断您的 table 统计数据实际上显示 table 有大约 2.21 亿行(尽管 table 统计数据是不准确的估计)。
我不能说我知道确切的公式来知道给定的值列表需要多少内存,但鉴于您观察到的行为,我们可以猜测它平均每项大约 600 字节,假设14k 项有效,超过则无效。
您可以设置range_optimizer_max_mem_size = 0
来禁用内存限制。这会产生过度使用内存的风险,但它避免了优化器“放弃”。我们在上一份工作中为所有 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_table
在 time,guid
上有主键,在 guid
上有索引
我上面写的查询有很好的性能,根据解释计划是 using index condition; using where; using MRR
随着我在 in
子句中增加值的数量,性能受到显着影响。
经过一些枯燥的 运行s,我能够得到一个粗略的数字。对于小于 ~14500 的值,解释计划与上面相同。对于高于此值的数量,仅解释计划 uses where
并且 运行 我的查询需要很长时间。
换句话说,例如,如果我在 in
子句中放入 14,000 个值,解释计划将按预期有 14,000 行。但是,如果我在我的 in
子句中放入 15,000 个值,则解释有 221200324 行。我整个 table 中甚至没有这么多行。
我正在尝试了解此行为并想知道是否有任何方法可以解决此问题。
谢谢
了解 Limiting Memory Use for Range Optimization。
当 IN()
谓词中有大量值时,它会在查询优化步骤中使用更多内存。在某些情况下,这被认为是一个问题,因此 MySQL 的最新版本设置了最大内存限制(默认为 8MB)。
如果优化器发现它需要的内存超过限制,则查询中没有其他条件可用于优化,它会放弃尝试优化,并求助于 table-scan。我推断您的 table 统计数据实际上显示 table 有大约 2.21 亿行(尽管 table 统计数据是不准确的估计)。
我不能说我知道确切的公式来知道给定的值列表需要多少内存,但鉴于您观察到的行为,我们可以猜测它平均每项大约 600 字节,假设14k 项有效,超过则无效。
您可以设置range_optimizer_max_mem_size = 0
来禁用内存限制。这会产生过度使用内存的风险,但它避免了优化器“放弃”。我们在上一份工作中为所有 MySQL 个实例设置了这个值,因为我们无法教育开发人员避免在他们的查询中创建大量值列表。