mysql НЕ оптимизирован ДЛЯ ЗАПРОСОВ

#mysql #sql #query-optimization

#mysql #sql #запрос-оптимизация

Вопрос:

У меня есть две таблицы, названные как:

  1. table_product
  2. table_user_ownned_auction

table_product

 specific_product_id      astatus  ... 
(primary_key,autoinc)
--------------------------------------
1                        APAST    ...
2                        ALIVE    ...
3                        ALIVE    ...
4                        APAST    ... 
5                        APAST    ...
  

table_user_ownned_auction

 own_id     specific_product_id   details   
----------------------------------------
1                  1               XXXX
2                  5               XXXX
  

Мне нужно выбрать atatus = APAST , а не в таблице 2.
Что означает, что в приведенной выше структуре table1 имеет статус 3 APAST (1,4,5). Но в таблице 2 хранится только specific_product_id (1,5), поэтому мне нужно выбрать specific_product_id = 4

Я использовал этот запрос

   SELECT * 
    FROM table_product 
   WHERE astatus = 'APAST' 
     AND specific_product_id NOT IN (SELECT specific_product_id 
                                       FROM table_user_ownned_auction )
  

…что занимает так много времени:

Запрос занял 115,1039 секунды

…для выполнения.

ОБЪЯСНИТЕ ПЛАН

введите описание изображения здесь

Как я могу оптимизировать его или любым другим способом выбрать то, что я хочу?

Ответ №1:

Используя NOT EXISTS

 SELECT p.* 
  FROM TABLE_PRODUCT p
 WHERE p.astatus = 'APAST' 
   AND NOT EXISTS (SELECT NULL
                     FROM TABLE_USER_OWNED_AUCTION uoa
                    WHERE uoa.specific_product_id = p.specific_product_id)
  

Используя LEFT JOIN/IS NULL

    SELECT p.* 
     FROM TABLE_PRODUCT p
LEFT JOIN TABLE_USER_OWNED_AUCTION uoa ON uoa.specific_product_id = p.specific_product_id
    WHERE p.astatus = 'APAST' 
      AND uoa.own_id IS NULL
  

Объяснение

Наиболее оптимальный запрос может быть определен по тому, являются ли столбцы, сравниваемые между двумя таблицами, обнуляемыми (т. Е. могут ли specific_product_id значения в любой таблице быть NULL ).

Добавление

Как только оптимальный запрос будет определен, взгляните на создание индексов (возможно, охватывающих индексы) по крайней мере для:

  • specific_product_id
  • TABLE_PRODUCT.astatus

Комментарии:

1. Мне понравилось ваше решение. Я изучаю mysql. Не могли бы вы, пожалуйста, объяснить мне, что будет выбрано в подзапросе в NOT EXISTS(..), когда uoa.specific_product_id != p.specific_product_id

2. @Sandeep: NOT выполняет отмену, чтобы изменить uoa.specific_product_id = p.specific_product_id на uoa.specific_product_id != p.specific_product_id .

3. В приложении один -> Один раз допущена опечатка.

4. Я прочитал вашу статью , на которую вы ссылаетесь, и кажется, что между LEFT JOIN/IS NULL и NOT IN нет разницы в производительности. Таким образом, вы могли бы сделать вывод, что вы могли бы просто всегда использовать NOT IN , и вы всегда защищены. Цитата для сравнения обоих в статье: «Алгоритмы фактически одинаковы, и запросы выполняются в одно и то же время».

Ответ №2:

Попробуйте добавить индекс в table_user_ownned_auction таблицу:

 ALTER TABLE table_user_ownned_auction ADD KEY(specific_product_id)
  

Кроме того, попробуйте использовать non-exists соединение:

 SELECT p.*
FROM table_product p
    LEFT JOIN table_user_ownned_auction l
      ON p.specific_product_id = l.specific_product_id
WHERE p.astatus = 'APAST' 
    AND l.specific_product_id IS NULL
  

Комментарии:

1. @gowri: Это также может быть связано с тем, что план запроса был кэширован

2. используйте точные имена полей вместо SELECT *