子查询与EXISTS与IN – MySQL
以下两个查询是子查询。 两者都是一样的,都为我工作得很好。 但问题是方法1查询需要约10秒执行,而方法2查询需要1秒以下。
我能够将方法1查询转换为方法2,但我不明白查询中发生了什么。 我一直在试图弄清楚自己。 我真的想知道下面两个查询之间有什么区别,性能增益如何发生? 它背后的逻辑是什么?
我是这些先进技术的新手。 我希望有人能帮助我。 鉴于我阅读的文件 ,不给我一个线索。
方法1:
SELECT * FROM tracker WHERE reservation_id IN ( SELECT reservation_id FROM tracker GROUP BY reservation_id HAVING ( method = 1 AND type = 0 AND Count(*) > 1 ) OR ( method = 1 AND type = 1 AND Count(*) > 1 ) OR ( method = 2 AND type = 2 AND Count(*) > 0 ) OR ( method = 3 AND type = 0 AND Count(*) > 0 ) OR ( method = 3 AND type = 1 AND Count(*) > 1 ) OR ( method = 3 AND type = 3 AND Count(*) > 0 ) )
方法2:
SELECT * FROM `tracker` t WHERE EXISTS ( SELECT reservation_id FROM `tracker` t3 WHERE t3.reservation_id = t.reservation_id GROUP BY reservation_id HAVING ( METHOD = 1 AND TYPE = 0 AND COUNT(*) > 1 ) OR ( METHOD = 1 AND TYPE = 1 AND COUNT(*) > 1 ) OR ( METHOD = 2 AND TYPE = 2 AND COUNT(*) > 0 ) OR ( METHOD = 3 AND TYPE = 0 AND COUNT(*) > 0 ) OR ( METHOD = 3 AND TYPE = 1 AND COUNT(*) > 1 ) OR ( METHOD = 3 AND TYPE = 3 AND COUNT(*) > 0 ) )
Explain Plan
会告诉你为什么你应该使用Exists
。 通常问题来自Exists vs Count(*)
。 Exists
速度更快。 为什么?
-
对于由NULL表示的挑战:当子查询返回
Null
,对于IN,整个查询变为Null
。 所以你也需要处理。 但是使用Exist
,这只是一个false
。 更容易应付。 简单的IN
不能和Null
比较,但Exists
可以。 -
例如
Exists (Select * from yourtable where bla = 'blabla');
一旦find/匹配,就会得到真/假。 -
在这种情况下,
IN
方式取决于Count(*)
的位置来根据WHERE
select所有匹配的行,因为它比较了所有的值。
但是不要忘记这一点:
-
EXISTS
对IN
高速执行:当子查询结果非常大时。 -
IN
超越EXISTS
:当子查询结果非常小时。
参考更多细节:
- 使用IN的子查询 。
- IN – 子查询优化
- join与子查询 。
方法2是快速的,因为它使用EXISTS
运算符,我的MySQL
不加载任何结果。 正如你的文档链接中提到的,它省略了SELECT
子句中的任何内容。 它只检查符合条件的第一个值,一旦发现它将条件设置为TRUE
并移动以进一步处理。
另一方面,方法1有IN
运算符,它载入所有可能的值然后匹配它。 只有在发现完全匹配的情况下,条件才被设置为TRUE
,这是耗时的过程。
因此你的方法2很快。
希望它有帮助…
第二种方法更快,因为你有这样的“WHERE t3.reservation_id = t.reservation_id”。 在第一种情况下,您的子查询必须对表进行全面扫描以validation信息。 然而,在2o方法中,子查询完全知道它在找什么,一旦发现被检查有条件的话。
他们的正式文件。 存在的子查询优化