我有一个用户和属于用户的facebook_accounts数据库。用户根据相对于其他用户拥有的积分数进行“排名”:这是通过嵌入的 SELECT 语句来完成的,该语句计算所有比该用户拥有更多积分的用户。
数据库有大约 10k 用户。以下 SQL 查询需要 MySQL 约 0.16 秒才能完成:
SELECT
*, (SELECT (COUNT(*) + 1)
FROM users AS UserHigher
WHERE UserHigher.points > User.points
) AS rank
FROM
users AS User
ORDER BY
User.points DESC, User.created ASC
LIMIT 0, 30
但是,添加 LEFT JOIN 来检索用户的 facebook_account 会挂起 MySQL:
SELECT
*, (SELECT (COUNT(*) + 1)
FROM users AS UserHigher
WHERE UserHigher.points > User.points
) AS rank
FROM
users AS User
LEFT JOIN
facebook_accounts AS FacebookAccount
ON (FacebookAccount.user_id = User.id)
ORDER BY
User.points DESC, User.created ASC
LIMIT 0, 30
我知道用于对用户进行排名的 COUNT() 选择方法效率有些低,但这是我遇到过的最可靠的方法。我不明白的是,为什么一个简单的 LEFT JOIN 会破坏原本合理的查询,而它似乎与排名 SELECT 语句完全分开。
有什么建议吗?
最佳答案
我的猜测是,原始查询首先进行排序,并且仅执行排名 30 次。第二个查询太复杂,MySQL 无法检测到这种优化。
以下内容可能会有所帮助:
select *
from (SELECT *, (SELECT (COUNT(*) + 1)
FROM users AS UserHigher
WHERE UserHigher.points > User.points
) AS rank
FROM users AS User
ORDER BY User.points DESC, User.created ASC
LIMIT 0, 30
) t join
facebook_accounts AS FacebookAccount
ON (FacebookAccount.user_id = User.id)
order by points desc, created asc
关于MySQL排名查询和LEFT JOIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15035467/