使用UNION ALL和ORDER BY优化查询

时间:2013-08-10 23:02:04

标签: mysql query-optimization database-performance

我有3个表(例如a,b,c),表示不同项目的活动(例如评论,喜欢等)以及每个活动的时间。我试图基本上做一种新闻提要,首先显示最近的活动。我为所有三个表构建了一个UNION ALL,将所有活动组合在一起,然后组建一个GROUP BY,以确保相同项目的活动不会显示两次,并按时间顺序显示DESC。此函数使用无限滚动,因此查询也必须能够适当地移动。

我想知道是否有任何方法可以优化这一点(每张表约为500-900K并且正在增长)。截断的代码如下所示。

SELECT time,item_id FROM (
   SELECT a.time AS time, a.item_id FROM a 
      UNION ALL 
   SELECT b.time AS time, b.item_id FROM b 
      UNION ALL 
   SELECT c.time AS time, c.item_id FROM c
) temp 
GROUP BY item_id 
ORDER BY time DESC 
LIMIT 10

1 个答案:

答案 0 :(得分:0)

您编写的查询将创建一个非常大的临时表。然后,您将按该临时表中的列进行排序。您应该尝试限制每个表,可能是这样的:

SELECT time,item_id FROM (
   SELECT a.time AS time, a.item_id FROM a LIMIT 10 ORDER BY time DESC 
      UNION ALL 
   SELECT b.time AS time, b.item_id FROM b LIMIT 10 ORDER BY time DESC 
      UNION ALL 
   SELECT c.time AS time, c.item_id FROM c LIMIT 10 ORDER BY time DESC 
) temp 
GROUP BY item_id 
ORDER BY time DESC 
LIMIT 10

您需要确保time在每个表上都有索引。

我不喜欢这样做,因为可能很难准确地“滚动”结果。

转到“下一页”时,您可能需要考虑添加WHERE条款,例如WHERE a/b/c.item_id > num而不是LIMIT offset, length。这将有助于提高准确性。

在编写查询时,您应在查询前加EXPLAIN,以查看 如何处理查询。这将使您更好地了解正在发生的事情:是否正在创建临时表?它有多大?正在使用哪些索引?等...

另一种方法可能是使用MySQL trigger填充单个“Feed”表。