db优化:计算排名

时间:2009-08-18 16:19:22

标签: database optimization

This question询问如何按用户ID选择用户的排名。

id     name     points
1      john     4635
3      tom      7364
4      bob      234
6      harry    9857

接受的答案是

SELECT  uo.*, 
        (
        SELECT  COUNT(*)
        FROM    users ui
        WHERE   (ui.points, ui.id) >= (uo.points, uo.id)
        ) AS rank
FROM    users uo
WHERE   id = @id

这是有道理的。我想了解这种方法之间的性能权衡,或者通过修改数据库结构来存储计算的排名(我想每次排名变化时需要进行大量更改),或任何其他方法太想新闻了。我是db noob。

3 个答案:

答案 0 :(得分:1)

性能权衡基本上与您所描述的相同:

如果您修改了结构以存储排名,那么查询将非常,非常简单和快速。但是,这会在任何时候“点”发生变化时需要一些开销,因为你必须验证排名没有改变。如果排名发生了变化,您必须进行多次更新。

这会在每次更新/插入时导致更多工作(可能存在错误)。权衡是非常快速的读取。如果您的典型用法是与数百万次读取相比很少的修改,并且您发现此查询是瓶颈,则可能值得考虑重新处理此问题。但是,除非您真正发现这是一个问题,否则我会避免增加复杂性和可维护性问题,因为当前的解决方案需要更少的存储空间,并且非常灵活。

答案 1 :(得分:1)

您引用的链接是MySQL问题。如果原始数据库是Oracle,那么接受的答案就是使用一个分析函数,它可以很好地扩展:

SQL> select id, name, points from users order by id
  2  /

        ID NAME           POINTS
---------- ---------- ----------
         1 john             4635
         3 tom              7364
         4 bob               234
         6 harry            9857
         8 algernon            1
         9 sebastian         234
        10 charles           888

7 rows selected.

SQL> select name, id, points, rank() over (order by points)
  2  from users
  3  /

NAME               ID     POINTS RANK()OVER(ORDERBYPOINTS)
---------- ---------- ---------- -------------------------
algernon            8          1                         1
bob                 4        234                         2
sebastian           9        234                         2
charles            10        888                         4
john                1       4635                         5
tom                 3       7364                         6
harry               6       9857                         7

7 rows selected.

SQL> select name, id, points, dense_rank() over (order by points desc)
  2  from users
  3  /

NAME               ID     POINTS DENSE_RANK()OVER(ORDERBYPOINTSDESC)
---------- ---------- ---------- -----------------------------------
harry               6       9857                                   1
tom                 3       7364                                   2
john                1       4635                                   3
charles            10        888                                   4
bob                 4        234                                   5
sebastian           9        234                                   5
algernon            8          1                                   6

7 rows selected.

SQL>

答案 2 :(得分:0)

该查询的“where”部分内部是否需要读取整个表?我理解过早优化。在学术上,似乎这不会超过几千行。