子查询与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(*)的位置来根据WHEREselect所有匹配的行,因为它比较了所有的值。

但是不要忘记这一点:

  • EXISTSIN高速执行:当子查询结果非常大时。
  • IN超越EXISTS :当子查询结果非常小时。

参考更多细节:

  • 使用IN的子查询 。
  • IN – 子查询优化
  • join与子查询 。

方法2是快速的,因为它使用EXISTS运算符,我的MySQL不加载任何结果。 正如你的文档链接中提到的,它省略了SELECT子句中的任何内容。 它只检查符合条件的第一个值,一旦发现它将条件设置为TRUE并移动以进一步处理。

另一方面,方法1有IN运算符,它载入所有可能的值然后匹配它。 只有在发现完全匹配的情况下,条件才被设置为TRUE ,这是耗时的过程。

因此你的方法2很快。

希望它有帮助…

第二种方法更快,因为你有这样的“WHERE t3.reservation_id = t.reservation_id”。 在第一种情况下,您的子查询必须对表进行全面扫描以validation信息。 然而,在2o方法中,子查询完全知道它在找什么,一旦发现被检查有条件的话。

他们的正式文件。 存在的子查询优化