Oracle中的分页最佳实践?

How*_*wie 27 oracle pagination

问题:我需要写存储过程(S)将返回行的单个页面的结果集总的行数.

解决方案A:我创建了两个存储过程,一个返回单个页面的结果集,另一个返回标量 - 总行数.解释计划说第一个sproc的成本为9,第二个的成本为3.

SELECT  *
FROM    ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) AS RowNum, ...
        ) AS PageResult
WHERE   RowNum >= @from
    AND RowNum < @to
ORDER BY RowNum

SELECT  COUNT(*)
FROM    ...
Run Code Online (Sandbox Code Playgroud)

解决方案B:我将所有内容都放在一个sproc中,方法是在结果集中的每一行添加相同的TotalRows数字.这个解决方案感觉很乱,但成本只有9,只有一个sproc,所以我倾向于使用这个解决方案.

SELECT * 
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC  ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
        AND RowNum < to
ORDER BY RowNum;
Run Code Online (Sandbox Code Playgroud)

Oracle中的分页是否有最佳实践?在实践中最常使用哪种上述解决方案?他们中的任何一个被认为是完全错误的?请注意,我的数据库将保持相对较小(小于10GB).

我正在使用Oracle 11g和最新的ODP.NET与VS2010 SP1和Entity Framework 4.4.我需要最终的解决方案才能在EF 4.4中运行.我相信一般来说可能有更好的分页方法,但是我需要他们使用EF.

Vin*_*rat 28

如果您已经在使用analytics(ROW_NUMBER() OVER ...),那么在同一分区上添加另一个分析函数将为查询添加可忽略的成本.

另一方面,还有许多其他方式可以进行分页,其中一种方法是使用rownum:

SELECT * 
  FROM (SELECT A.*, rownum rn
          FROM (SELECT *
                  FROM your_table
                 ORDER BY col) A
         WHERE rownum <= :Y)
 WHERE rn >= :X
Run Code Online (Sandbox Code Playgroud)

如果您在订购列上有适当的索引,那么此方法将更加出色.在这种情况下,使用两个查询可能更有效(一个用于总行数,一个用于结果).

这两种方法都是合适的,但一般情况下,如果您想要行数和分页集,那么使用分析更有效,因为您只查询行一次.

  • 在Oracle Magazine(2006年9月/ 10月)中查看Tom Kyte"[在ROWNUM和限制结果中](http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html)" . (2认同)

Art*_*Art 5

这可能会有所帮助:

   SELECT * FROM 
     ( SELECT deptno, ename, sal, ROW_NUMBER() OVER (ORDER BY ename) Row_Num FROM emp)
     WHERE Row_Num BETWEEN 5 and 10;
Run Code Online (Sandbox Code Playgroud)

  • 好吧,我在上面写了这个MAY的帮助。对不起,如果我没有帮助您。我试过了... (4认同)
  • 这正是 OP 在问题中所拥有的内容......您必须解释_为什么_它会有所帮助,因为 OP 正在寻找性能最高的解决方案。为什么这比使用 rownum 更好,在什么情况下?你有什么基准吗? (2认同)

Taj*_*der 5

在 Oracle 12C 中,您可以使用限制LIMITOFFSET进行分页。

示例 - 假设您有一个表tab,需要使用分页根据DATE数据类型列dt按降序从该表中获取数据。

page_size:=5

select * from tab
order by dt desc
OFFSET nvl(page_no-1,1)*page_size ROWS FETCH NEXT page_size ROWS ONLY;
Run Code Online (Sandbox Code Playgroud)

解释:

page_no=1 page_size=5

OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY - 仅获取第一 5 行

page_no=2 page_size=5

OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY - 获取接下来的 5 行

等等。

参考页面 -

https://dba-presents.com/index.php/databases/oracle/31-new-pagination-method-in-oracle-12c-offset-fetch

https://oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1#paging