我在 mysql 中有 5 个表。当我想要执行查询时,它执行的时间太长。 我的表格结构如下:
- 收据(行数:23799640)reciept table structure
- reciept_goods(行数:39398989)reciept_goods table structure
- 好(行数:17514)good table structure
- good_categories(行数:121)good_categories table structure
- retail_category(行数:10)retail_category table structure
我的索引:
- 日期 -->reciept.date #1
- reciept_goods_index -->reciept_goods.recieptId #1, reciept_goods.shopId #2, receive_goods.goodId #3
- category_id -->good.category_id #1
我有下一个 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
解释此查询给出下一个结果: Explain query 执行时间 = 236 秒
if use straight_join good ON (good.id = reciept_goods.GoodId )
解释查询
Explain query
执行时间 = 31 秒
SELECT STRAIGHT_JOIN ... rest of query
我想,这个问题出现在我的表索引中,但我不知道如何修复它们,有人可以帮助我吗?
最佳答案
由于 reciepts
中大约 2% 的行具有正确的日期,因此选择的第二个执行计划(使用 Straight_join)似乎是正确的执行顺序。您应该能够通过添加以下覆盖索引来优化它:
reciept(date, sales)
reciept_goods(recieptId, shopId, goodId, amount)
我假设 reciept_goods
主键中的列顺序当前为 (goodId, recieptId, shopId)
(或 (goodId, shopId,receiptId)
)。您可以将其更改为 recieptId, shopId, goodId
(如果您查看例如表名称,您可能无论如何都想这样做);在这种情况下,您不需要第二个索引(至少对于此查询)。我假设这个主键使 MySQL 采取较慢的执行计划(当然假设它会更快)——尽管有时这只是糟糕的统计数据,尤其是在测试服务器上。
有了这些覆盖索引,即使没有 straight_join
,MySQL 也应该采用更快的解释计划,如果没有,只需再次添加它(尽管我想看看两个执行计划)。还要检查解释计划中是否使用了这两个新索引,否则我可能会错过一列。
关于mysql - 优化Mysql索引多表JOIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51896204/