【问题标题】:Paging choice, on database or in the web application分页选择,在数据库或 Web 应用程序中
【发布时间】:2011-05-27 12:27:14
【问题描述】:

我正在考虑重新设计我们网站的报告页面以提高速度,但我对如何实现分页持观望态度。我们的数据库很大,超过 1.5 亿条记录。我们的大多数报告都需要来自多达 5 到 10 个表的复杂数据,因此每个表可能有 5 或 6 个连接和一些内部选择。显然,它们不是快速查询。

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

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

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

【问题讨论】:

    标签: .net oracle pagination paging


    【解决方案1】:

    根据我的经验,如果留给数据库,分页总是更快。毕竟数据库是用来查询和操作海量数据的。

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

    【讨论】:

    • 那么缓存在一个实际的缓存中呢?
    【解决方案2】:

    您可以通过如下分析同时获取分页行数:

    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

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

    • 用户定期在结果集中向前/向后移动,而无需刷新数据
    • 网络带宽和可用内存(应用程序端)是足够的(很可能这只有在同时用户数量保持较小的情况下才有可能)

    【讨论】:

    • 所以如果我的查询返回 10,000 行,这个查询将为每一行调用 'count(*) over() nb_rows'?我应该担心这一点,还是运行该计数所需的时间可以忽略不计?
    • @Zach:这是一个解析函数,每个“窗口”都会计算一次(这里只有一次)。
    【解决方案3】:

    在数据库中进行。对于 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 个,您将有 lower=1 和 Higher=10)

    这里的诀窍是:

    1. 确保使用 order by 的内部选择相当快(使用正确的索引)。
    2. 使用 rownum 可以让 Oracle 做一个停止键,这有助于限制它需要处理的行。

    至于你的情况,如果你有一个复杂的查询需要时间运行并返回大量数据,你肯定要先创建一个物化视图,添加一个索引或二是支持对快照表的查询,然后在需要的时候刷新完成。您上面的查询将来自 mat 视图,而不是来自基表。

    【讨论】:

    • 我认为物化视图在某些情况下可能是一个不错的主意,但由于我们的要求,它对我们不起作用。用户进入我们的站点,添加项目,并立即运行报告以查看他们有权查看的项目(以及项目的谱系)(确定访问是使我们的查询复杂化和减慢查询的一部分,因为用户可以拥有或不拥有根据一长串必须检查的规则访问项目)。
    • 我明白了,我认为这是用户运行相当静态的报告(每天刷新一次或两次)。听起来这更像是一个数据库设计问题而不是分页问题,​​如果您的要求是这样的并且要完成它,您需要为每个用户每次运行 60 秒的查询,分页可能是您最不担心的问题。对不起。
    • 同意!对于 95% 的用户来说,查询很快,但有些用户的数据量非常大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 2012-05-27
    • 2021-05-30
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 2011-06-15
    相关资源
    最近更新 更多