我有一个相当大的查询,运行速度很慢。一开始大约需要15分钟。然后我添加了所有适当的索引并将其降低到30秒。这是昨天。现在,我添加了2个新连接,实际上将一些LEFT JOIN
更改为INNER
,现在需要20多分钟才能运行。
以下是查询的EXPLAIN
。我将一个Excel文件上传到SkyDrive,其中包含结果:http://cid-a32b31fdac0efced.office.live.com/view.aspx/mysqlexplain.xlsx
你会在这里看到有一张桌子,mwd,它说它没有钥匙。我检查了这个表,确实附上了相应的索引。但是,这不是我添加到联接中的表,昨天运行正常。
我创建的新联接可以在第28和29行看到。
非常感谢任何帮助。
编辑:编辑:我再次运行查询而没有mwd
表中的字段,即。 BIR3M
,dealer_code
,country_code
,dsm_dealer_number
,location_number
,dms_type
,sequence_number
,version_no_edr
,{{ 1}},id_dms_type
,version_no_dms
,它现在可以在4秒内运行! (它仍在加入此表)
我知道它找不到version_date_dms
的密钥,即使在正确的字段上有索引,那么我该怎么办呢?
编辑:真的不想发布查询,工作的东西。但这是加入的第一部分,导致延迟。这很长......
mwd
答案 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子句中的索引。
您还需要在以下列中添加索引