#mysql #max
#mysql #max
Вопрос:
Я беру последнюю цену от конкретного продукта, но производительность действительно низкая для более чем 3 миллионов цен.
У кого-нибудь есть лучший способ сделать это? Мой сервер загружается этим медленным запросом.
prices.id
используется для хранения идентификатора магазина в prices
таблице, чтобы я мог объединить его с stores.id
из stores
таблицы.
SELECT prices.id, prices.price, prices.timelog, prices.user_id FROM prices
WHERE prices.id IN (SELECT stores.id FROM stores WHERE city = "miami" )
AND prices.product_id = 1
AND prices.timelog IN
(SELECT MAX( lastprice.timelog )
FROM prices AS lastprice
WHERE lastprice.id = prices.id AND lastprice.product_id = 1)
Комментарии:
1. Не могли бы вы, пожалуйста, показать нам индексы, которые у вас есть в таблице
prices
иstores
?
Ответ №1:
Не видя структуры таблиц, я думаю, вы могли бы сделать:
select * from prices
join stores on stores.id = prices.id
where stores.city = 'miami' and prices.product = 1
order by timelog DESC LIMIT 1
Комментарии:
1. У MySQL
top 1
было быLIMIT 1
в конце AFAIK.2. @Richard, очень хорошая компактная переписать
3. @caio, используй ответ Ричарда и убедись, что
stores.id
иprices.id
являются первичными ключами для этих таблиц. Также убедитесь, что у вас есть индекс наtimelog
,stores.city
и наprices.product
.4. @Johan:
prices.id
не похоже на первичный ключ. Возможно, его лучше переименовать вprices.storeid
.5. @ypercube, теперь, когда вы упомянули об этом, это действительно выглядит как странное объединение, может ли это быть причиной
join using ...
заболевания?
Ответ №2:
3 миллиона цен могут означать, что ваше приложение может извлечь выгоду из некоторой денормализации. (т. Е. Каким-либо образом отметьте последнюю цену, помните: запись-один раз, чтение-много часто стоит накладных расходов на более медленную запись).
С текущими данными стоит попробовать:
SELECT p1.id, p1.price, p1.timelog, p1.user_id
FROM prices p1
JOIN stores
ON stores.id = prices.id
AND stores.city = "miami"
LEFT JOIN prices p2
ON p2.product_id = p1.product_id
AND p2.id = p1.id
AND p2.timelog > p1.timelog
WHERE p1.product_id = 1 AND p2.id IS NULL;
… и еще один немного более быстрый вариант, который всегда ускользает от меня в это время ночи 🙂
Имейте в виду, что многое может измениться с правильными индексами в таблицах, поэтому, во что бы то ни стало, запустите EXPLAIN
для лота.
Комментарии:
1. потрясающе, это было в 4,5 раза быстрее, чем оригинал.
Ответ №3:
Попробуйте это тоже:
SELECT prices.id
, prices.price
, prices.timelog
, prices.user_id
FROM prices
JOIN
( SELECT MAX( timelog ) AS lasttimelog
FROM prices
WHERE product_id = 1
) AS lastprice
ON prices.timelog = lastprice.lasttimelog
WHERE EXISTS
( SELECT *
FROM stores
WHERE prices.id = stores.id
AND stores.city = "miami"
)
AND prices.product_id = 1
Я бы предположил, что индекс в (id,product_id,timelog)
in products
и индекс в id
или (city,id)
в таблице stores
помогут ускорить запрос.
Было бы лучше, если бы вы запускали EXPLAIN для запросов, а также публиковали структуру таблиц (поля, индексы, ссылки).