У меня 5 таблиц в mysql. И когда я хочу выполнить запрос, он выполняется слишком долго. Есть структура моих таблиц:
Мои показатели:
У меня есть следующий запрос sql:
SELECT
R.shopId,
sales,
sum(Amount) as sum_amount,
count(distinct R.id) as count_reciept,
RC.id,
RC.name
FROM
reciept R
JOIN reciept_goods RG
ON R.id = RG.RecieptId
AND R.ShopID = RG.ShopId
JOIN good G
ON RG.GoodId = G.id
JOIN good_categories GC
ON G.category_id = GC.id
JOIN retail_category RC
ON GC.retail_category_id = RC.id
WHERE
R.date >= '2018-01-01 10:00:00'
GROUP BY
R.shopId,
R.sales,
RC.id
Объяснение этого запроса дает следующий результат: Объяснить запрос и время выполнения = 236 сек.
если использовать straight_join good ON (good.id = reciept_goods.GoodId )
объяснить запрос Объяснить запрос и время выполнения = 31 с
SELECT STRAIGHT_JOIN ... rest of query
Я думаю, эта проблема в индексах моих таблиц, но я не понимаю, как их исправить, может кто-нибудь мне помочь?
Примерно 2% ваших строк в reciepts
имеющих правильную дату, выбранный второй план выполнения (с помощью straight_join) представляется правильным порядком выполнения. Вы можете оптимизировать его, добавив следующие индексы покрытия:
reciept(date, sales)
reciept_goods(recieptId, shopId, goodId, amount)
Я предполагаю, что порядок столбцов в вашем основном ключе для reciept_goods
настоящее время (goodId, recieptId, shopId)
(или (goodId, shopId, receiptId)
). Вы можете изменить это, чтобы recieptId, shopId, goodId
(и если вы посмотрите, например, на имя таблицы, вы, возможно, захотите сделать это в любом случае); в этом случае вам не нужен второй индекс (по крайней мере для этого запроса). Я бы предположил, что этот первичный ключ заставил MySQL принять более медленный план выполнения (конечно, предполагая, что он будет быстрее), хотя иногда это просто плохая статистика, особенно на тестовом сервере.
С теми, которые охватывают индексы, MySQL должен принять более быстрый план объяснения даже без straight_join
, если это не так, просто добавьте его снова (хотя я бы хотел посмотреть на оба плана выполнения). Также проверьте, что эти два новых индекса используются в плане объяснения, иначе я, возможно, пропустил столбец.
show create table reciept_goods
, что действительно изменили первичный ключ (с помощью show create table reciept_goods
он также сообщает вам, используете ли вы MyISAM)? Не могли бы вы добавить планы выполнения для коротких и длинных диапазонов дат? Я предполагаю , что использование straight_join
держит ваш запрос быстро, так что у вас есть обходной путь для вашей насущной проблемы? Несвязанный, но любопытный: изменение ПК улучшило скорость выполнения? Вы добавили первый индекс?
Похоже, вы зависите от того, как пройти через пару из многих: много таблиц? Многие люди проектируют их неэффективно.
Здесь я составил список из 7 советов по созданию более эффективных таблиц сопоставления. Наиболее важным является использование составных индексов.
reciept
имеетdate>='2018-01-01 10:00:00'
? Есть ли значительное количество рецептов, которые имеют 0 строк вreciept_goods
? Кроме того: 31s подходит для вас, и вы просто хотите знать, зачем вам нужно прямое соединение или какое время выполнения вам нужно? (Я знаю, это никогда не может быть достаточно быстрым ...)