#mysql #sql #query-optimization
#mysql #sql #запрос-оптимизация
Вопрос:
У меня есть две таблицы, названные как:
- table_product
- 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
).
- Если nullable,
NOT IN
илиNOT EXISTS
является лучшим выбором в MySQL - Если НЕ имеет значения null, `LEFT JOIN/РАВНО NULL — лучший выбор в MySQL
Добавление
Как только оптимальный запрос будет определен, взгляните на создание индексов (возможно, охватывающих индексы) по крайней мере для:
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 *