Oracle 中分页的最佳实践?
问题:我需要编写存储过程来返回单页行的结果集和总行数.
Problem: I need write stored procedure(s) that will return result set of a single page of rows and the number of total rows.
解决方案 A:我创建了两个存储过程,一个返回单个页面的结果集,另一个返回标量 - 总行数.解释计划说第一个 sproc 的成本为 9,第二个成本为 3.
Solution A: I create two stored procedures, one that returns a results set of a single page and another that returns a scalar -- total rows. The Explain Plan says the first sproc has a cost of 9 and the second has a cost of 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 ...
解决方案 B:我将所有内容都放在一个 sproc 中,方法是将相同的 TotalRows
编号添加到结果集中的每一行.这个解决方案感觉很hackish,但是成本是9,而且只有一个sproc,所以我倾向于使用这个解决方案.
Solution B: I put everything in a single sproc, by adding the same TotalRows
number to every row in the result set. This solution feel hackish, but has a cost of 9 and only one sproc, so I'm inclined to use this solution.
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY D.ID DESC ) RowNum, COUNT(*) OVER () TotalRows,
WHERE RowNum >= from
AND RowNum < to
ORDER BY RowNum;
在 Oracle 中是否有最佳的分页实践?上述哪种解决方案在实践中最常用?他们中的任何一个被认为是完全错误的吗?请注意,我的数据库现在并将保持相对较小(小于 10GB).
Is there a best-practice for pagination in Oracle? Which of the aforementioned solutions is most used in practice? Is any of them considered just plain wrong? Note that my DB is and will stay relatively small (less than 10GB).
我正在使用 Oracle 11g 和最新的 ODP.NET 以及 VS2010 SP1 和 Entity Framework 4.4.我需要在 EF 4.4 中工作的最终解决方案.我确信一般来说可能有更好的分页方法,但我需要它们与 EF 一起使用.
I'm using Oracle 11g and the latest ODP.NET with VS2010 SP1 and Entity Framework 4.4. I need the final solution to work within the EF 4.4. I'm sure there are probably better methods out there for pagination in general, but I need them working with EF.
推荐答案
如果您已经在使用分析 (ROW_NUMBER() OVER ...
) 那么在同一分区上添加另一个分析函数将为查询添加可忽略的成本.
If you're already using analytics (ROW_NUMBER() OVER ...
) then adding another analytic function on the same partitioning will add a negligible cost to the query.
另一方面,还有许多其他的分页方式,其中一种使用rownum
:
On the other hand, there are many other ways to do pagination, one of them using rownum
:
SELECT *
FROM (SELECT A.*, rownum rn
FROM (SELECT *
FROM your_table
ORDER BY col) A
WHERE rownum <= :Y)
WHERE rn >= :X
如果您在排序列上有合适的索引,这种方法会更好.在这种情况下,使用两个查询(一个查询总行数,一个查询结果)可能更有效.
This method will be superior if you have an appropriate index on the ordering column. In this case, it might be more efficient to use two queries (one for the total number of rows, one for the result).
这两种方法都是合适的,但一般来说,如果您想要行数和分页集,那么使用分析会更有效,因为您只查询一次行.
Both methods are appropriate but in general if you want both the number of rows and a pagination set then using analytics is more efficient because you only query the rows once.
相关文章