【问题标题】:Is MySQL smart enough to stop considering rows once HAVING condition must be true?一旦 HAVING 条件必须为真,MySQL 是否足够聪明以停止考虑行?
【发布时间】:2018-03-04 14:38:42
【问题描述】:
想象一下这样的查询
SELECT col1
FROM t
GROUP BY col2
HAVING COUNT(col3) > 1;
col2 上有可用索引的地方。当 MySQL 扫描 col2 索引并计算 COUNT(col3) 时,它会在计数超过 1 时立即停止计数并向前扫描到下一个唯一的 col2 值吗?还是会考虑每一行并获得准确的计数,然后在完全汇总后将其与 1 进行比较?
【问题讨论】:
标签:
mysql
group-by
query-optimization
【解决方案1】:
这是有根据的推测。当HAVING 子句为真时,MySQL 不够聪明,无法停止。为什么?因为 MySQL 先执行GROUP BY,然后执行ORDER BY。据我所知,它不会将过滤推入聚合步骤——即使使用索引也是如此。
让我们忽略SELECT col1,这在此查询中没有意义。
如果col2/col3 对是唯一的,那么您可能会通过以下方式获得更好的性能:
SELECT col1
FROM t
WHERE EXISTS (SELECT 1
FROM t t2
WHERE t2.col2 = t.col2 AND t2.col3 <> t.col3
);
这将在第一个匹配的 col3 行处停止。如果情况是您确实在检查 NULL 的值 col3,那么:
SELECT col1
FROM t
WHERE EXISTS (SELECT 1
FROM t t2
WHERE t2.col2 = t.col2 AND t2.col3 IS NOT NULL AND t2.id <> t.id
) AND
col3 IS NOT NULL;
后两个查询假设您在t(col2, col3) 上有一个索引。