2012-06-25 149 views
0

我一直在负责支持的客户端慢得令人痛苦的应用程序。我启用了MySQL slow_query_log并发现了一些似乎是罪魁祸首的查询。我对这个查询做了些什么感到有点困惑,但任何关于如何重写这个的建议都会有所帮助。很慢执行MySQL查询

SELECT 
    table_a.id AS table_a_id_1, 
    table_a2.id AS table_a_id_2 
FROM 
    table_a, 
    table_b 
LEFT JOIN 
    table_a AS table_a2 
ON 
    table_a.value = table_a2.value 
WHERE 
    table_a.value_id = 112 AND 
    table_a2.value_id = 113 AND 
    table_a.status != table_a2.status AND 
    table_a.id = table_b.id; 

对我来说,它看起来像查询从单个表中选择相同的数据两次,然后做与选定的一些数据比较,以及执行与表-B联接为好。这里是MySQL引用这个查询执行的日志。

Query_time: 160.854398 
Lock_time: 0.000139 
Rows_sent: 12 
Rows_examined: 10339025 

任何建议你可以提供将是有益的!

+0

我甚至不认为这个查询是有效的......你确定它运行正确吗?在发布之前是否对查询进行了任何更改? –

+0

我也不认为它是有效的,它对我来说看起来很奇怪。但是,它运行时不会产生错误并返回行。我对查询做的唯一更改是用table_a和table_b ...替换表名。 我会检查,看看是否我可以张贴实际的完整的查询,如果你认为这将有助于。这真的更令人困惑......哈哈! –

+1

这是一个不好的极端思想结合显式和隐式连接(使用隐式连接在所有的是SQL反模式)。只需修复以使用明确的连接即可获得帮助,那么您需要修复查询中出现错误的部分。在@ GordonLinoff的回答中看到我的评论。 – HLGEM

回答

3

这是可能的查询计划是建立一个交叉连接,如WHERE子句中指定:

SELECT table_a.id AS table_a_id_1, 
     table_a2.id AS table_a_id_2 
FROM table_a join 
    table_b 
    on table_a.id = table_b.id LEFT JOIN 
    table_a AS table_a2 
    ON table_a.value = table_a2.value 
WHERE table_a.value_id = 112 AND 
     table_a2.value_id = 113 AND 
     table_a.status != table_a2.status 

这也表明,在table_a.id和table_a.value和table_b.id索引可能帮助很多。现在

,你也许可以简化这个查询了很多。例如,它似乎在table_a中获得112,113对,其状态不同。我真的不知道table_b在哪里被使用,除非有一些过滤标准。你可以更有效地得到这个列表doiing类似的东西:

SELECT table_a.id AS table_a_id_1, 
     table_a2.id AS table_a_id_2 
FROM (select ta.* from table_a ta where ta.value_id = 112) ta join 
    (select ta.* from table_a ta where ta.value_id = 113) ta2 
    ON ta.value = ta2.value and 
     ta.status != ta2.status 
+0

table_a2.value_id = 113需要是在where子句中或要转换左连接到内连接。而table_a.status!= table_a2.status需要合并以避免将空值与值进行比较。 – HLGEM

+0

我在这里做一个连接,并将左连接转换为常规连接。我认为左连接是多余的,因为原始查询中的where子句确保table_a2端的NULL值被删除。但是,我从来没有真正想过左连接在“开”的条件不引用第一个表,所以我不是在这种情况下,知道什么SQL指定(或MySQL做什么)。也许它会在前两个表上进行交叉连接,并且这个连接还会被连接到第三个表上? –