我很好奇MySQL是否会在内部优化同一列上有两个或更多WHERE X IN Y
条件的查询。
作为我问的原因的快速背景:有问题的应用程序使用PHP查询构建器,并在两个不同的位置将条件添加到查询中。基于权限的限制首先在代码的一个区域中自动添加到查询中。在一个单独的区域中,检索到受限制的SELECT
查询对象(无需了解之前的操作),并且除了基于权限的限制之外,还添加了其他用户选择的过滤器限制,这可能导致两个{{ 1}}一个领域的条件。
对于一个小的人为例子,假设有一个简单的表格,如:
WHERE
(显然还会添加适当的索引)
因此,在构建CREATE TABLE users (
userId INT(12) NOT NULL auto_increment,
managerUserId INT(12),
name VARCHAR(16)
primary KEY (userId)
);
查询时,我们最初会从SELECT
开始。
例如,假设进行查询的用户可以访问以下managerUserId值:11,22,33,44,55,66,77。
查询构建器将自动强加SELECT * FROM users
裸查询。现在我们有查询对象表示的查询WHERE managerUserId IN (11,22,33,44,55,66,77)
。
但是,用户指定他们只需要有关managerUserId值的信息:33,55,77。
由于这是用户请求的过滤器而不是与访问相关的限制,因此会在代码中的不同位置修改查询,以将SELECT * FROM users WHERE managerUserId IN (11,22,33,44,55,66,77)
添加到AND managerUserId IN (33,55,77)
子句中。
此时我们现在有了最终查询:
WHERE
现在,显然我们只需要实际查询(11,22,33,44,55,66,77)和(33,55,77)的联合。
我的问题是:MySQL是否知道如何在内部优化上述查询,只需等同于
SELECT *
FROM users
WHERE managerUserId IN (11,22,33,44,55,66,77)
AND managerUserId IN (33,55,77)
在我的情况下,第一个基于访问的限制可能包含最多100-200个值,而第二个限制在大多数情况下可能只包含十几个或更少的值。对我来说似乎很简单MySQL可以检测到优化,但我不确定如何确认是这种情况,或者包含这两个条款的潜在性能问题可能是什么。
答案 0 :(得分:1)
快速回答是:是,在这种情况下,MySql能够优化查询。
详细信息如下所述:http://dev.mysql.com/doc/refman/5.7/en/range-optimization.html
最有趣的部分描述如下: 8.2.1.3.1。单部分索引的范围访问方法
在这里:http://dev.mysql.com/doc/refman/5.7/en/range-optimization.html#equality-range-optimization
他们说有这些条件的查询:
col_name IN(val1,...,valN)
col_name = val1 OR ... OR col_name = valN
被视为(或定义)为:
等式范围比较(“范围”是单个值)。
所以第一段(8.2.1.3.1。范围访问方法......)也与这些查询有关。
文档中描述了该算法的详细信息,简而言之:MySql从WHERE子句中提取“范围”(值),然后组合重叠范围,并删除空范围。