有没有办法优化这个SQL服务器查询?

时间:2013-05-15 12:32:40

标签: mysql performance

我有3张桌子:

表1

id   |   name
1    |   joe
2    |   peter
3    |   sandra

表2

id   |   fkId   |   date_updated
1    |    1     |   2013-01-31
2    |    1     |   2013-04-01
3    |    2     |   2013-02-04
4    |    2     |   2013-01-02

表3

id   |   fkId   |   date_updated
1    |    1     |   2013-01-31
2    |    3     |   2013-04-01
3    |    3     |   2013-02-04
4    |    2     |   2013-01-02

我有以下内容:

SELECT * 
FROM 
     table1
LEFT OUTER JOIN 
     table2 ON table1.id = table2.fkId
LEFT OUTER JOIN 
     table3 ON table1.id = table3.fkId
GROUP BY 
     table1.id
HAVING 
     table2.date_updated = max(table2.date_updated)
     AND table3.date_updated = max(table3.date_updated)

我的输出如下:

 name |   table2   |  table3  
joe   | 2013-04-01 | 2013-01-31
peter | 2013-02-04 | 2013-01-02
sandra|            | 2013-04-01

我得到了我需要的数据,但这个查询花了太长时间,无论如何要优化它而不修改表索引?

要指出的事情:

  • table2和table3不是同一个表。

  • 我需要得到#34; last_updated"来自table2和table3,而不仅仅是日期。

编辑**

使用WHERE table1.id = id时,查询大约需要3-4秒,以返回单个记录。

表1有~84000个记录

表2有~96000个记录

表3有~81000个记录

2 个答案:

答案 0 :(得分:1)

根据您显示的数据,查询似乎是:

SELECT table1.name, MAX(table2.date_updated), MAX(table3.date_updated)
FROM  table1 LEFT OUTER JOIN 
      table2
      ON table1.id = table2.fkId LEFT OUTER JOIN 
      table3 ON table1.id = table3.fkId
GROUP BY table1.id

table2(fkid, date_updated)和table3(fkid,date_updated)的索引可能会有所帮助。

实际上,对于这样的索引,这个版本可能会有更好的性能:

select table1.name,
       (select date_updated from table2 where table1.id = table2.fkid order by date_updated desc limit 1
       ) as T2,
       (select date_updated from table3 where table1.id = table3.fkid order by date_updated desc limit 1
       ) as T3
from table1

这完全消除了分组,用相关的子查询替换它 - 相关的子查询应该变成索引小索引扫描。

答案 1 :(得分:0)

我知道你在没有修改索引的情况下提到了,但是如果每个“Table2”和“Table3”都有索引,那么你想要做的只会更加优化

(fkId,date_updated)。

如果每个表的“ID”列上只有一个索引,那么显然没有任何内容可以在连接上进行优化。您至少需要在Table1的外键上使用它。但由于这将是桌面上的一个新索引,它不应该伤害任何东西,而只是帮助你的查询。在BOTH Table2和Table3上做这个索引。