У меня есть большая таблица, которая использовалась для записи количества запасов, она уже заказана time_create.
Теперь я хочу получить последнюю информацию о количестве товаров на складе в каждом магазине.
Код:
select SQ.store_id,SQ.product_id, max(SQ.time_create) as last_time, SQ.store_product_quantity_new
from stockquantitylogs as SQ
where SQ.time_create > unix_timestamp("2018-08-01")*1000
group by SQ.store_id, SQ.product_id
Но это очень-очень медленно.
Поэтому мне интересно, как сделать мой запрос более эффективным.
PS: SQ.store_product_quantity_new
достается от max(SQ.time_create)
? Не уверен в этом, просто хочу получить store_product_quantity_new
с max(SQ.time_create)
Состав
create table stockquantitylogs
(
id char(36) collate utf8_bin default '' not null
primary key,
store_id char(36) collate utf8_bin default '' not null,
product_id char(36) collate utf8_bin default '' not null,
time_create bigint not null,
time_update bigint not null,
store_product_quantity_old int not null,
store_product_quantity_new int not null
);
create index IX_product_id
on stockquantitylogs (product_id);
create index IX_store_id
on stockquantitylogs (store_id);
create index IX_time_create
on stockquantitylogs (time_create);
create index IX_time_update
on stockquantitylogs (time_update);
Таблицы - это unordered sets
, ТОЛЬКО при запросе на order by
вы можете гарантировать, что он будет представлен в ожидаемом порядке.
Думаю, было бы полезнее: meta.stackoverflow.com/questions/333952/…
Какую версию MySQL вы используете?
@Deebster 5.6 Думаю
@Mithril, пожалуйста, опубликуйте также результаты Explain Statement. Кроме того, учитывая, что первичным ключом является Char, а store_id также является Char (вместо Int), они определенно будут иметь более низкую производительность по сравнению с использованием Int.
Следуйте за тегом, который я добавил.
Вы не можете просто использовать max () для столбца и автоматически выбирать другие столбцы из той же строки. В более поздних версиях MySQL опция ONLY_FULL_GROUP_BY включена по умолчанию, что означает, что даже попытка выполнения этого запроса является ошибкой (см. https://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html).
Вам нужно выяснить, какие строки вам нужны, а затем выбрать их:
SELECT sq.store_id, sq.product_id, sq.time_create AS last_time, sq.store_product_quantity_new
FROM stockquantitylogs AS sq
INNER JOIN (
SELECT store_id, product_id, MAX(time_create) AS time_create
FROM stockquantitylogs
GROUP BY store_id, product_id
) AS sq_latest USING(store_id, product_id, time_create)
Здесь мы сначала выбираем желаемые (последние) строки с помощью:
SELECT store_id, product_id, MAX(time_create) AS time_create
FROM stockquantitylogs
GROUP BY store_id, product_id
Затем внешний запрос выбирает строки для возврата путем присоединения к совпадающим строкам из внутренних результатов.
Чтобы это работало хорошо, вам понадобится индекс для соответствующих строк:
INDEX `store_id_product_id_time_create` (`store_id`, `product_id`, `time_create`)
Обратите внимание, что я удалил ваш оператор where - если это необходимо, добавьте его во внутренний запрос sq_latest
.
Структура таблицы (с деталями индексации) с результатами оператора EXPLAIN будет полезна