优化我的SQL索引多表JOIN

时间:2018-08-17 13:12:00

标签: mysql database join indexing

我在mysql中有5个表。当我要执行查询时,它执行时间过长。 我的表格结构如下:

  1. 收据(计数行:23799640)reciept table structure
  2. reciept_goods(计数行:39398989)reciept_goods table structure
  3. 好(行数:17514)good table structure
  4. good_categories(计数行:121)good_categories table structure
  5. retail_category(行数:10)retail_category table structure

我的索引:

  1. 日期->接收日期#1
  2. reciept_goods_index->​​ reciept_goods.recieptId#1,                          reciept_goods.shopId#2,                          reciept_goods.goodId#3
  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秒

如果使用straight_join good ON (good.id = reciept_goods.GoodId )解释查询 Explain query 执行时间为31秒

SELECT STRAIGHT_JOIN ... rest of query

我认为,表索引中存在该问题,但是我不理解如何解决它们,有人可以帮我吗?

2 个答案:

答案 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个技巧列表,以提高映射表的效率。最重要的是使用复合索引。