我在mysql中有5个表。当我要执行查询时,它执行时间过长。 我的表格结构如下:
我的索引:
我有下一个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秒
如果使用straight_join good ON (good.id = reciept_goods.GoodId )
解释查询
Explain query
执行时间为31秒
SELECT STRAIGHT_JOIN ... rest of query
我认为,表索引中存在该问题,但是我不理解如何解决它们,有人可以帮我吗?
答案 0 :(得分:0)
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也应该采取更快的解释计划,如果没有,只需再次添加它(尽管我想看看两个执行计划)。还要检查说明计划中是否使用了这两个新索引,否则我可能错过了专栏。
答案 1 :(得分:0)
似乎您要依靠走过许多桌:许多桌?许多人没有效率地设计它们。
Here我整理了7个技巧列表,以提高映射表的效率。最重要的是使用复合索引。