如何使用 EXIST 而不是 IN 使用 MySQL
Posted
技术标签:
【中文标题】如何使用 EXIST 而不是 IN 使用 MySQL【英文标题】:how to use EXIST instead of IN using MySQL 【发布时间】:2014-02-16 00:28:14 【问题描述】:如何将这个查询“转换”为不使用 IN,我读到的 in 与存在相比很慢
SELECT * FROM kx_examenes_diagnostico.examenes t1 WHERE NOT EXISTS (
SELECT * FROM kx_examenes_diagnostico.examenes_aplicados t2 WHERE t2.alumno_id=812 AND t2.examen_id=t1.examen_id
) AND t1.examen_id IN (1,2,3,4,5,10,11,12,13,,50,159,635,456,780,12,63,45);
我使用 mysql,我不知道如何使用我比较的值(在 in 子句内部)我必须使用 OR 的存在吗?有可能吗?
谢谢
【问题讨论】:
in
当你有一个常量列表时很好。性能问题是存在子查询时。
当IN
子句在主键/索引列上选择时,它几乎是尽可能快的,因为该行可以直接从索引中获取,应该可以通过二进制搜索进行排序。跨度>
“In”和“exists”不一定做同样的事情。两者都有时间和地点。获得正确的结果应该是最重要的。然后你就可以担心速度了。
【参考方案1】:
不清楚为什么要重写查询以消除 IN 列表。可以重写查询以替换 col IN (literal list)
谓词,但这不会提高性能。
如果您希望提高性能,则更有可能想要消除
NOT EXISTS (correlated_subquery)
谓词,并使用“反连接”模式替换它,如下所示:
SELECT t1.*
FROM kx_examenes_diagnostico.examenes t1
LEFT
JOIN kx_examenes_diagnostico.examenes_aplicados t2
ON t2.examen_id=t1.examen_id
AND t2.alumno_id=812
WHERE t1.examen_id IN (1,2,3,4,5,10,11,12,13,50,159,635,456,780,12,63,45)
AND t2.examen_id IS NULL
“反连接”模式是一个外连接(包括来自t1
且在t2
中没有任何匹配行的行)与一个谓词(WHERE 子句)相结合,该谓词消除了确实有匹配。
为了这个特定查询的最佳性能,您可能需要索引
... ON examenes (examen_id)
... ON examenes_aplicados (examen_id, alumno_id)
根据alumno_id
列的基数,此索引可能会更好:
... ON examenes_aplicados (alumno_id, examen_id)
examenes_aplicados
上的这两个索引中的任何一个都是“覆盖索引”,这意味着 MySQL 可以通过访问索引页面来满足查询,而无需访问基础表中的页面。我们希望 MySQL EXPLAIN
显示“Using index
”以访问该表。
更新:
我避免回答您提出的问题,而是回答了一个完全不同的问题。要回答您提出的问题:
问:我必须使用 OR 吗?
不,您不必使用 OR 关键字。 IN 列表可以替换为不使用任何 OR
关键字的等效谓词。
问:有可能吗?
是的,可以用EXISTS
子句替换IN (list)
谓词。但是您确实不想这样做,除非您的目标是可怕的表现,并且您希望 DBA 追捕您以惩罚您,公开羞辱您,并殴打您。
【讨论】:
以上是关于如何使用 EXIST 而不是 IN 使用 MySQL的主要内容,如果未能解决你的问题,请参考以下文章