我的网站上有一个热门列表页面,它在特定列中获取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都被编入索引,但很明显索引不用于此查询。有没有办法通过某种方式编辑查询或索引来提高性能?
答案 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行,那么很好。否则,请转到原始查询。