MySQL查询运行速度非常慢

时间:2011-03-17 14:54:29

标签: mysql

我有一个相当大的查询,运行速度很慢。一开始大约需要15分钟。然后我添加了所有适当的索引并将其降低到30秒。这是昨天。现在,我添加了2个新连接,实际上将一些LEFT JOIN更改为INNER,现在需要20多分钟才能运行。

以下是查询的EXPLAIN。我将一个Excel文件上传到SkyDrive,其中包含结果:http://cid-a32b31fdac0efced.office.live.com/view.aspx/mysqlexplain.xlsx

你会在这里看到有一张桌子,mwd,它说它没有钥匙。我检查了这个表,确实附上了相应的索引。但是,这不是我添加到联接中的表,昨天运行正常。

我创建的新联接可以在第28和29行看到。

非常感谢任何帮助。

编辑:编辑:我再次运行查询而没有mwd表中的字段,即。 BIR3Mdealer_codecountry_codedsm_dealer_numberlocation_numberdms_typesequence_numberversion_no_edr,{{ 1}},id_dms_typeversion_no_dms,它现在可以在4秒内运行! (它仍在加入此表)

我知道它找不到version_date_dms的密钥,即使在正确的字段上有索引,那么我该怎么办呢?

编辑:真的不想发布查询,工作的东西。但这是加入的第一部分,导致延迟。这很长......

mwd

3 个答案:

答案 0 :(得分:1)

好的,我重新调整了JOIN的顺序并移动了:

INNER JOIN mwd ON mwd.department_id = I.department_id

成为第一个JOIN。现在查询需要8秒!所以这就是固定的。但任何人都可以解释为什么会这样吗?

答案 1 :(得分:1)

每当您的查询涉及如此多的表时 - 通常都会出现设计问题。抛开这一点,我注意到你混合了LEFT(OUTER)和INNER JOIN。

除非表之间存在特定的依赖关系,例如

A LEFT JOIN B on (a..b) INNER JOIN C on (c..b)

(C必须在b之后)

您应该尽早将所有INNER JOIN组合在一起,例如而不是

A LEFT JOIN B on (a..b) INNER JOIN C on (c..a)

将其写为

A INNER JOIN C on (c..a) LEFT JOIN B on (a..b)

这将有助于优化器首先处理INNER JOIN,这可能会减少行数。根据定义,LEFT JOIN保留前面表中的所有行,因此优化器通常会在以后的表中执行这些行。

答案 2 :(得分:0)

到目前为止,我可以在查询结尾看到优化:

例如,这可以重写

WHERE I.department_id IN (120, 322, 362)
    AND I.created_date BETWEEN '2011-03-01 00:00:00' AND '2011-03-02 23:59:59'
    AND ibev.booking_item_id IS NULL AND NOT ibi.booking_item_type_id IN (10,14) AND ibi.warranty_percentage > 0
    AND wb.booking_id IN (454017, 454019, 454021, 454031)

进入

       JOIN (SELECT 120 AS d 
             UNION ALL 
             SELECT 322 AS d 
             UNION ALL 
             SELECT 362) d1 
         ON d1.d = i.department_id 
       JOIN (SELECT 454017 AS b 
             UNION ALL 
             SELECT 454019 AS b 
             UNION ALL 
             SELECT 454021 AS b 
             UNION ALL 
             SELECT 454031 AS b) d2 
         ON d2.b = wb.booking_id 
       LEFT JOIN (SELECT 10 AS bt 
                  UNION ALL 
                  SELECT 14 AS bt) d3 
         ON d3.bt <> ibi.booking_item_type_id 
WHERE  i.created_date BETWEEN '2011-03-01 00:00:00' AND '2011-03-02 23:59:59' 
       AND ibev.booking_item_id IS NULL 
       AND ibi.warranty_percentage > 0 

我们采用IN选项并放入派生的静态表,以便在匹配时 - ON子句 - 应该使用索引。 MySQL使用连接上的索引,但不使用IN子句中的索引。

您还需要在以下列中添加索引

  • I.department_id
  • wb.booking_id
  • ibi.booking_item_type_id