Подзапросы с EXISTS vs IN-MySQL

ниже два запроса подзапросы. Оба они одинаковы, и оба отлично работают для меня. Но проблема в том, что запрос метода 1 занимает около 10 секунд, а запрос Метода 2 занимает менее 1 секунды.

я смог преобразовать запрос метода 1 в Метод 2, но я не понимаю, что происходит в запросе. Я и сам пытался это выяснить. Я действительно хотел бы узнать, в чем разница между двумя ниже запросами и как происходит повышение производительности ? какая логика? за ним ?

Я новичок в этих передовых технологий. Надеюсь, кто-нибудь мне поможет. Учитывая, что я читал docs что не дает мне подсказки.

Способ 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
         )                                             
   )

5 ответов


An Explain Plan показал бы вам, почему именно вы должны использовать Exists. Обычно возникает вопрос Exists vs Count(*). Exists быстрее. Почему?

  • в отношении вызовов, присутствующих NULL: when вложенный запрос возвращает Null, ибо во всем запросе становится Null. Так что с этим тоже нужно разобраться. Но используя Exist, просто false. Гораздо легче справиться. Просто IN ничего не могу сравнить с Null но Exists может.

  • например Exists (Select * from yourtable where bla = 'blabla'); вы получаете true/false момент один удар найдена строкой.

  • в этом случае IN занимает должность Count(*) выберите все соответствующие строки на основе WHERE потому что он сравнивает все значения.

но не забывайте и этого:

  • EXISTS выполняет в высокая скорость против IN: когда результаты подзапроса очень велики.
  • IN обгоняет EXISTS : когда результаты подзапроса очень мало.

ссылка на более подробную информацию:


Метод 2 быстрый, потому что он использует EXISTS оператор, где I MySQL Не загружайте результаты. Как упоминалось в вашем docs ссылка также, что она опускает все, что есть в SELECT предложения. Он проверяет только первое значение, которое соответствует критериям, после его обнаружения задает условие TRUE и перемещается для дальнейшей обработки.

С другой стороны, метод 1 имеет IN оператор, который загружает все возможные значения, а затем сопоставляет его. Условие TRUE только когда найдено точное совпадение, что является трудоемким процессом.

следовательно, ваш метод 2 быстрый.

надеюсь, что это помогает...


второй метод быстрее, потому что у вас есть это, как там "где t3.reservation_id = Т.reservation_id". В первом случае ваш подзапрос должен выполнить полное сканирование в таблицу для проверки информации. Однако при методе 2o подзапрос точно знает, что он ищет, и как только он найден, проверяется условие наличия.


на оператор логический оператор, который возвращает true или false. Оператор EXISTS часто используется в подзапрос для проверки на "exist" состояние.

SELECT 
    select_list
FROM
    a_table
WHERE
    [NOT] EXISTS(subquery);

Если подзапрос возвращает все строки оператор возвращает true, иначе возвращает false.

кроме того, оператор немедленно завершает дальнейшую обработку, как только находит соответствующую строку. Из-за этой характеристики вы можете использовать оператор для повышения производительности запроса в некоторых случаях.

на не оператор перечеркивает оператора. Другими словами,НЕ СУЩЕСТВУЕТ возвращает true, если подзапрос не возвращает строку, в противном случае он возвращает false.

можно использовать выберите *, выберите столбец, выберите a_constant, или что-нибудь в подзапрос. Результаты одинаковы, потому что MySQL игнорирует select_list в инструкции это появляется в выберите предложения.

причина в том, что оператор работает на основе принципа" по крайней мере, найдено". Он возвращает true и останавливает сканирование таблицы один раз, по крайней мере, одна соответствующая строка найдена.

С другой стороны, когда на оператор объединяется с подзапросом, MySQL должен сначала обработать подзапрос, а затем использует результат подзапроса для обработки всего запроса.

общее правило большого пальца заключается в том, что если подзапрос содержит большой объем данных оператор обеспечивает лучшую производительность.

однако запрос, который использует на оператор будет работать быстрее, если результирующий набор, возвращаемый подзапросом очень мало.

для подробных объяснений и примеров: MySQL существует - mysqltutorial.org


Их Официальная Документация.оптимизация подзапросов с помощью Exists