【问题标题】:Nhibernate Paging performance on large table (10,000,000 rows)大型表(10,000,000 行)上的 Nhibernate 分页性能
【发布时间】:2012-02-16 18:52:20
【问题描述】:

我有一个相当大的表,大约有 10,000,000 行。我需要从我的 C# 应用程序中翻阅此表。我正在使用 NHibernate。我曾尝试使用此代码示例:

return session.CreateCriteria(typeof(T))
                .SetFirstResult(startId)
                .SetMaxResults(pageSize)
                .List<T>();

当我执行它时,如果我的 startId 大于 7,000,000,操作最终会超时。我使用的 pageSize 是 200。我已经在小于 1000 行的小得多的表上使用了这种方法,而且它工作起来很快。

问题是,在这么大的桌子上,有没有更好的方法来使用 NHibernate 完成这个任务?

【问题讨论】:

  • 哪个rdbms?或者 SQL 是什么样的?也许尝试在那里扔一个 OrderBy...
  • 它是 MSSQL2005。立即尝试订购。
  • 顺序实际上没有任何区别,但我确实发现将 startId 更改为较低的值可以完成操作。它似乎以大约 7,000,000 或更高的 startId 值窒息。任何较低的东西都是缓慢的,但至少完成。
  • 您能否启动 SQL Server Profiler 并查看触发了哪个查询?然后从工作室手动启动它。这不一定是 NHibernate 的问题。您的 NHibernate 查询可能无法在 SQL 中应用限制,但稍后会修剪该结果。
  • 你说得对,是 SQL Server 速度慢。我从 SQL Server Profiler 中提取查询并从 Management Studio 中运行它。花了将近一分钟。所以,我的问题仍然存在,有没有更有效的方法来使用 NHibernate 做到这一点?我们试图摆脱存储过程,因为它们难以管理。

标签: sql-server nhibernate paging


【解决方案1】:

您试图一次翻阅 1000 万行 200 行?为什么?没有人会翻阅那么多数据。

您需要先过滤数据集,然后将 TSQL 样式分页应用于较小的数据集。 Here are some methods that will work。只需修改它们,以便通过某种过滤(WHERE 子句、CTE 或派生表)获得少于 1000 万行。

【讨论】:

  • 不错的链接。我也看到了很多关于分页的评论“..你为什么要..”。在许多情况下,这只是一个业务需求。我正在开发一个导入平面文本文件(一些包含数十万行)的系统。我们提供了在文件导入后查看文件的功能,我不会加载所有行供他们查看,因此分页似乎是一个理想的解决方案。更复杂的是,用户希望能够按不同的列进行排序,因此虽然他们可能不想翻阅整个文件,但他们需要一些机制来查看数据。
  • 我以前有过这个要求。没有人会翻阅数据。假设每页 1 秒,他们需要 138 小时才能读完。他们想要的是查看一个样本集,看看有 1000 万个可用。为他们提供良好的索引和搜索重要字段的方法,他们应该很高兴。你正在努力解决一些永远不会像他们所说的那样被使用的东西。我会深入研究这些要求,使它们得到改进。向他们展示他们有多疯狂。解释和展示替代方案。你是房间里知识渊博的人。
  • 我们并不是要读取 10M 条记录,但我们可能只想查看最后几百条记录。也许你可以为此提出一个替代策略。
  • 除了重组查询之外别无其他,这样您就可以处理过滤列表,而不是尝试分页那么多数据。过滤和排序 TSQL 真的很擅长。分页,尽管如此,但使用上面链接中的查询会让您有所帮助。
  • @GrantFritchey 你是对的,浏览每一行需要很长时间。我也同意您所说的关于过滤和排序的说法,但是,如果您的过滤和排序查询仍然返回大量行,则需要分页。用户是否选择查看所有页面取决于他们。我所做的只是提供功能,以尽我所能提供最佳性能。
【解决方案2】:

有趣的是,您应该提出这个问题,因为我遇到了同样的问题。我的问题与使用 NHibernate 的分页无关,而更多地与使用直接 T-SQL 相关。

似乎有几个选项。我发现在我的实例中非常有用的一个是this answer 用于有关分页的问题。它讨论了使用“..keyset 驱动的解决方案”,而不是通过使用 ROW_NUMBER() 返回排名结果。我不确定 NHibernate 在这种情况下会使用什么,或者是否可以看到它根据您发出的查询生成的 SQL(我知道您可以在 Hibernate 中,但我没有使用过 NHibernate)。

如果您不知道使用 SQL SERVER 根据 ROW_NUMBER 返回排名结果,那么值得研究一下。很多人似乎参考this article 来了解如何进行分页。我已经看到一些后续帖子不鼓励使用 SET ROWCOUNT,但支持使用带有动态参数的 TOP - SELECT TOP(@NumOfResults)。

这里有很多关于这个的帖子,但据我所知,没有关于最好的解决方法的明确答案。我会密切关注这篇文章,看看其他人的建议。

【讨论】:

    【解决方案3】:

    可能是隔离层问题。

    我有类似的问题。 如果您从中读取的表不断更新,则更新程序会锁定部分表,导致超时然后从表中读取。 添加 SetIsolationLayer(ReadUncommitted) 必须注意数据可能有点脏。

    【讨论】:

    • 感谢您的建议,isolationLayer 已设置为 ReadUncommited。
    猜你喜欢
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 2011-08-05
    • 2011-06-11
    • 2010-11-24
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多