EXISTS与IN的子查询 - MySQL

Tec*_*hie 20 mysql sql phpmyadmin subquery query-optimization

以下两个查询是子查询.两者都是一样的,两者都适合我.但问题是方法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 
         )
   )
Run Code Online (Sandbox Code Playgroud)

方法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
         )                                             
   )
Run Code Online (Sandbox Code Playgroud)

bon*_*igo 49

一个Explain Plan会显示你到底为什么你应该使用Exists.通常问题来了Exists vs Count(*). Exists是比较快的.为什么?

  • 关于NULL所呈现的挑战:当子查询返回时Null,对于IN整个查询变为Null.所以你也需要处理它.但使用Exist,它只是一个false.更容易应对.简直IN无法比较任何东西,NullExists可以.

  • 例如Exists (Select * from yourtable where bla = 'blabla');,在找到/匹配一个命中的那一刻,你得到真/假.

  • 在这种情况下,IN排序采取Count(*)选择所有匹配行的位置,WHERE因为它比较所有值.

但是不要忘记这个:

  • EXISTS高速执行IN:当子查询结果非常大时.
  • IN领先于EXISTS:子查询结果非常小.

参考更多详情:

  • 20行是大还是小? (2认同)