mysql - 优化Mysql索引多表JOIN

标签 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. 日期 -->reciept.date #1
  2. reciept_goods_index -->reciept_goods.recieptId #1, reciept_goods.shopId #2, receive_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 秒

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/

相关文章:

database - 敏捷——数据库部署

php - 为什么当我合并 mysql 数据库中的表时,值是重复的?

javascript - Sequelize .set 错误,.set 不是函数

javascript - 在 Javascript 中加入

mysql - 获取列名

MySQL : Initialize mySql variable inside a query

php - 用这个表结构结交PHP和MYSQL的 friend

mysql 需要很长时间才能获取 sum()

C# ASP.NET 简单选择问题

java - 如何以正确的方式对字符进行编码和解码