0

我有 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 不是同一张表。

  • 我需要从 table2 和 table3 中获取“last_updated”的整行,而不仅仅是日期。

编辑 **

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

表 1 有 ~ 84000 条记录

表 2 有 ~ 96000 条记录

Table3 有 ~ 81000 条记录

4

2 回答 2

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

这完全消除了分组,将其替换为相关子查询——并且相关子查询应该变成索引小索引扫描。

于 2013-05-15T14:47:45.647 回答
0

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

( fkId, date_updated )。

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

于 2013-05-15T13:41:24.853 回答