假设我有以下包含 3 个整数字段的数据库表。
A | B | C
1 | 2 | 3
1 | 2 | 4
1 | 3 | 1
2 | 4 | 2
2 | 4 | 3
当我做:
SELECT * FROM dbTable ORDER BY A,B LIMIT 1;
我得到
1 | 2 | 3
这是预期的。但是第二条记录:
1 | 2 | 4
dbFields A 和 B 也具有相同的值。是否有任何有效的方法来实际检索与 top-k 记录具有相同值的所有记录?例如,当我搜索前 100 条记录而不是 102 条记录时,如果后两条记录的值与第 100 条记录相同?是否有任何索引可以加速此类查询?如果实现有效,我不介意是否必须使用 pl/pgsql(而不是纯 SQL)来完成。
您可以为此使用窗口函数:
rank()
对于“第一”行,使用or并不重要dense_rank()
。例如,当您想要“第二个”时,如果出现平局,rank()
和dense_rank()
将返回不同的结果。因为rank()
数字会有“差距”,但dense_rank()
不会。通过分两步执行此操作可以实现可能的加速,当然还有一个索引
(a,b)
这个想法是让 Postgres 有机会对排名部分进行仅索引扫描,然后仅将扫描的结果连接到基表以获得剩余的列。排名过滤是在 CTE 内部完成的,因为 Postgres 不会将条件从外部查询下推到 CTE 本身(这就是为什么我在 CTE 内部有派生表)
我不确定这是否真的提高了性能,但我想值得尝试并查看带有真实表(和数据)的执行计划。
这就是我想出的:
似乎是正确的,但请发现任何可能的疏忽。