有效获取25行,最高两列总和(MySQL)

时间:2014-02-23 18:44:58

标签: mysql sql optimization indexing

我的网站上有一个热门列表页面,它在特定列中获取25个具有最高值的行。如果基于一列(例如得分),我在获取顶级列表时没有问题,但是当涉及更多列时,我遇到了一些性能问题。

在有问题的情况下,我想选择25行,按照降序排列两列的总和。

SELECT username, rank1 + rank2 AS rank FROM users ORDER BY rank DESC LIMIT 25

查询有效,但大约需要0.25秒才能完成,而单列上的查询大约需要0.0003。以下是解释查询的结果:

id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows   | Extra
1  | SIMPLE      | accounts | ALL  | NULL          | NULL | NULL    | NULL | 517874 | Using filesort

rank1和rank2都被编入索引,但很明显索引不用于此查询。有没有办法通过某种方式编辑查询或索引来提高性能?

1 个答案:

答案 0 :(得分:2)

MySQL不能很好地处理这种情况。其他数据库(例如,Oracle,Postgres,SQL Server)提供某种形式的基于功能的索引,可直接解决此问题。要在MySQL中执行此操作,需要向表中添加新列,然后添加触发器以使其保持最新。最后是新专栏的索引。也许很多工作。

在某些情况下,您可以假设总和的前三名将在每个排名的前YYY中。如果这是真的,那么诸如此类的查询将提高性能:

select ur1.*
from (select u.*
      from users u
      order by rank1 desc
      limit 1000
     ) ur1 join
     (select u.*
      from users u
      order by rank2 desc
      limit 1000
     ) ur2
     on ur1.username = ur2.username
order by ur1.rank1 + ur1.rank2 desc
limit 25;

这将按每个排名提取前1000个(或任何值),然后识别两个列表共有的用户。 希望有25个这样的用户(适合您的应用)。至少,这应该比整体查询更好。你可以先试试这个。如果它返回25行,那么很好。否则,请转到原始查询。