【问题标题】:Performance Issues loading large data set into c# GridView将大型数据集加载到 c# GridView 中的性能问题
【发布时间】:2013-08-01 12:24:08
【问题描述】:

好的,

在我的 GridView 中测试了相对较小的数据集,一切正常。但是,我现在已进入正确的 UAT 并尝试将 17,000 条记录加载到我的 Grid 中,这基本上使我的 Web 应用程序陷入了停滞。

基本上,用户登录,并在验证后加载所有数据网格,其中一个包含 17k 条记录。直到所有内容都加载完毕,最终用户才会留在登录页面上。所以我需要修复它。

网格的代码是:

DataTable dtValueDateCurrency = null;               
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["Reporting"].ConnectionString);
using (conn)
{
    conn.Open();
    //Load all other grid data
    using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(TSQL1, conn))
    {
        dtValueDateSummary = new DataTable();
        sqlAdapter.Fill(dtValueDateSummary);
        grdValueDateSummary.DataSource = dtValueDateSummary;
        grdValueDateSummary.DataBind();
    }
 }

有没有办法增加加载时间?分页不是一个选项,因为我正在使用 JQuery 来处理这个问题。

【问题讨论】:

  • 不要从数据库中加载 17k 条记录,而是使用数据库分页(例如通过ROW_NUMBER 函数)。不要将这么多的记录数据绑定到您的GridView,而是使用服务器端分页而不是 jquery。你看过生成的 HTML 吗?然后你就会知道为什么它很慢。
  • Performance Issues loading large data set into c# GridView == "不要将大型数据集加载到 c# GridView"
  • 通过数据读取器而不是数据适配器从数据库添加记录可能会得到更好的响应。我知道它更适合大型数据集。基本上你会手动填充数据表......当它击中 gridview.bind() 时你仍然会受到打击
  • 根据您对此处的答案的 cmets,让我更笼统地说:永远不要尝试在网络上加载 17,000 条记录。这不是GridView 问题。这不是DataReaderDataAdapter 的问题。对于一页来说,这只是太多的信息。这必须发生在服务器上。您必须更改分页和过滤选项才能以不同的方式工作,但它们仍然可以工作。

标签: c# asp.net gridview


【解决方案1】:

在一个查询中加载 17,000 条记录是让您丧命的事情。我强烈建议对您的 gridview 进行分页。

首先你需要改变你的存储过程如下。

ALTER PROCEDURE [dbo].[SomeTable_GetPagedResults] 
( 
        @StartRowIndex      int, 
        @MaximumRows        int 
) 

AS 
SET NOCOUNT ON 

Select 
    RowNum, 
    [ID], 
    [foo],
    [bar]
From 
    (Select 
        [ID], 
        [foo], 
        [bar], 
        Row_Number() Over(Order By [ID] Desc) As RowNum 
        From dbo.[SomeTable] t) 
As DerivedTableName 
Where RowNum Between @StartRowIndex And (@StartRowIndex + @MaximumRows) 

现在您有了一个可分页的查询。

您还需要一个查询来获取完整的行数。

ALTER PROCEDURE [dbo].[SomeTable_GetRowCount] 

AS 
SET NOCOUNT ON 

return (Select Count(ID) As TotalRecords From SomeTable) 

每次更改页面时都会绑定网格。

protected void gridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
  gridView1.PageIndex = e.NewPageIndex;
  BindGrid(); // this is whatever method you call to bind your data and execute your stored procedure.
}

BindGrid() 方法将调用您的两个存储过程(一个用于获取完整的行数,一个用于获取与当前页面相关的结果)

Additional Reading

【讨论】:

  • 为什么不能两者都做?您不能认真地在一个页面上显示所有 17000 条记录。谁会在那乱七八糟的东西中拖放任何东西?我真的认为你需要重新考虑你的方法。
  • 我觉得这是一个不好的方法。更好的方法是简单地使用过滤器要求对服务器进行 ajax 调用。在启用分页的情况下将这些反馈给应用程序。
  • 这个答案仍在每次调用中检索所有 17,000 条记录,但现在它只显示一页数据。
  • 你可以切换到中继器,但绝对是数据,而不是标记,让事情陷入困境。
  • 我不想强调这一点,但 .NET 仍然必须将这些记录处理到内存中的对象中,这可能不一定需要 1-2 秒。不过,您已经获得了代码并且可以对其进行测试,所以我在这一点上听从您的意见。
【解决方案2】:

您需要建立数据库分页。

这将涉及创建自定义排序、自定义过滤和自定义分页,但它会显着提高代码的性能,因为您一次只能从数据库中检索一页数据,而不是一次全部 17,000 行。

我在一个银行应用程序中实现了这一点,该应用程序旨在显示、排序和过滤数十万笔贷款。答案太复杂,无法举一个简单的例子,但从研究数据库分页开始。使用 LINQ,它会给你简单的TakeSkip 方法来实现最简单的分页。

【讨论】:

    【解决方案3】:

    您应该考虑在 Web 服务器上缓存查询,尤其是在不经常更新的情况下。这样,所有客户端都可以简单地浏览缓存而不是无情地访问数据库。

    this SO question

    【讨论】:

    • 这不会解决对 17000 条记录的初始调用。分解请求(分页/延迟加载)是解决此问题的唯一方法。
    • 他可以让它在 Application_Start 上加载到缓存中。
    • @GarrisonNeely 有个想法
    • 确实,抱歉,我没有更具体地将其加载到 Applicaton_Start 上的缓存中。等式的另一部分是处理陈旧的数据——你必须弄清楚你的网络服务器什么时候应该更新缓存。有很多事情要做!
    • 更不用说,一旦他使用 jquery 拖放,缓存就需要完全更新以反映更改。
    【解决方案4】:

    真的,加载一次 17k 记录是没有用的,即使用户不能一次看到整个 17k 记录。我建议您将分页与 DataTable.Merge 函数一起使用,该函数有助于以块的形式加载记录并将新获取的数据附加到前一个数据中。我只是做了一个快速测试并找到了解决方案。 Give this a try.

    【讨论】:

      【解决方案5】:

      没有解决分页速度慢,会一次又一次调用数据库, 所以你需要 放

      <style>.body{display:none;}</style>
      

      页面开始 并在页面末尾

      <style>.body{display:block;}</style>
      

      【讨论】:

        猜你喜欢
        • 2019-06-29
        • 2011-08-05
        • 2015-02-27
        • 2021-01-05
        • 1970-01-01
        • 2018-11-09
        • 2011-05-28
        • 1970-01-01
        • 2017-11-16
        相关资源
        最近更新 更多