分页选择,在数据库或Web应用程序中

时间:2011-05-27 12:27:14

标签: .net oracle pagination paging

我正在考虑将网站的报告页面重新设计得更快,而且我正在研究如何实现分页。我们的数据库很大,> 1.5亿条记录。我们的大多数报告都需要来自最多5到10个表的复杂数据,因此每个表可能有5个或6个连接以及一些内部选择。显然,它们不是快速查询。

要在数据库端实现分页,对于每个Web请求,我需要在数据库中查询当前页面的行(例如100个中的100个),但我还需要再次查询数据库以获取总数可能的行。因此,我基本上运行整个查询两次,因为获取记录总数的查询仍然需要执行所有连接和内部选择以确定总数。

运行查询一次,返回所有结果,将其缓存在会话中,并使用Web代码进行分页是不是更好?我知道我最初会提取更多数据,但我只运行一次可能需要30到60秒而不是两次的查询。

这是一种技术通用问题,但如果重要,我使用.net 4.0和Oracle 11g。

3 个答案:

答案 0 :(得分:3)

您可以使用以下分析获取与分页行同时的行数:

SELECT [cols], nb_rows
  FROM (SELECT [cols], nb_rows, rownum r
          FROM (SELECT [cols], count(*) over() nb_rows
                  FROM [your_query])
         WHERE rownum <= :M)
 WHERE r >= :N

这将确保您只运行一次查询,并减轻您的网络带宽压力。

有关进一步分析,请参阅Speed of paged queries in Oracle

在以下情况下缓存整个查询的结果可能有意义:

  • 用户定期向前/向后移动结果集而无需刷新数据
  • 网络带宽和可用内存(应用程序端)就足够了(如果同时保留的用户数量很少,这种情况很可能就会出现这种情况)

答案 1 :(得分:3)

根据我的经验,如果留给数据库,分页总是更快。毕竟构建了一个数据库来查询和操作大量数据。

如果您在.NET中返回大量数据并在会话中“缓存”它,您的服务器上的内存将很快耗尽。

答案 2 :(得分:1)

在数据库中执行此操作。对于Oracle,您可以尝试类似:

select * 
  from ( select a.*, rownum r 
           from ( select *
                    from t
                   where x = :host_variable
                   order by y ) a
          where rownum <= :HigherBound )
 where r >= :LowerBound

其中LowerBound和HigherBound定义您的页面边界(对于第1页显示每页10个,您有更低= 1和更高= 10)

这里的诀窍是:

  1. 确保您的内部选择顺序相当快(使用适当的索引)。
  2. 使用rownum可以让Oracle执行一个stopkey,这有助于限制它需要处理的行。
  3. 至于你的情况,如果你有一个复杂的查询,需要时间来运行并返回大量的数据,你肯定想先创建一个物化视图,添加索引或两个支持快照表上的查询,然后在需要时刷新完成。您上面的查询将来自mat视图,而不是来自基表。