0

我有一个属于用户的用户facebook_accounts数据库。用户根据他们相对于其他用户的点数来“排名”:这是通过嵌入的 SELECT 语句来完成的,该语句计算所有用户的点数比用户多。

该数据库有大约 10k 用户。以下 SQL 查询需要 MySQL ~0.16s 才能完成:

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 语句完全分开时,为什么它会破坏原本合理的查询。

有什么建议吗?

4

1 回答 1

1

我的猜测是原始查询首先进行排序并且仅执行排名 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
于 2013-02-23T00:27:52.427 回答