好的,我正致力于将 oracle DB 的查询移植到postgres。我的查询需要给我编号记录,以及分页。
考虑以下oracle代码:
select * from (
select RS.*, ROWNUM as RN from (
select * from STUDENTS order by GRADES
) RS where ROWNUM <= (#{startIndex} + #{pageSize})
) where RN > #{startIndex}
请注意,ROWNUM
有两种用途:
我需要将此类查询移植到postgres 。
我知道如何使用LIMIT
和OFFSET
命令对分页进行分页,但我无法提供全局行号(查询结果中的每一行都会获得唯一的行号)。
另一方面,我能够找到可以为我提供全局行号的ROW_NUMBER()
命令,但由于我的数据库中的元组数量非常大,因此不会因为分页而推荐。
如何在postgres中编写类似的代码?
答案 0 :(得分:1)
解决方案在PostgreSQL中看起来更简单:
SELECT *,
row_number() OVER (ORDER BY grades) AS rn
FROM students
ORDER BY grades
OFFSET $1 LIMIT $2;
如果grades
上有索引并且偏移量不是太高,那么该查询是有效的:
EXPLAIN (ANALYZE)
SELECT *,
row_number() OVER (ORDER BY grades) AS rn
FROM students
ORDER BY grades
OFFSET 10 LIMIT 20;
QUERY PLAN
-------------------------------------------------------------------
Limit (cost=1.01..2.49 rows=20 width=20)
(actual time=0.204..0.365 rows=20 loops=1)
-> WindowAgg (cost=0.28..74.25 rows=1000 width=20)
(actual time=0.109..0.334 rows=30 loops=1)
-> Index Scan using students_grades_idx on students
(cost=0.28..59.25 rows=1000 width=12)
(actual time=0.085..0.204 rows=30 loops=1)
Planning time: 0.515 ms
Execution time: 0.627 ms
(5 rows)
观察计划中的actual
值。
OFFSET
的分页总是效率低,偏差很大;考虑keyset pagination。