1

我正在使用 Linq2Sql 返回存储过程的结果。sproc 在 2 秒内提供 100,000 条记录。应用 ToList() 需要 2 多分钟。

该项目是一个 ASP.NET WebForm。在代码隐藏中,我试图从事务系统中获取记录,以对仪表板类型的报告应用各种分析。10 万条记录是平均一个月的数据量。使用较小的数据一切正常。

using (FooDataContext dbml = new FooDataContext())
{
    var query = dbml.FooBar(OneParam, TwoParam, ThreeParam);
    //no delay

    var results = query.ToList();
    //takes over 2 minutes -- consistent network traffic throughout

    ReportGenerator.PivotTable(results);
    ReportGenerator.Chart(results);
    //etc.
}

我使用 ToList() 来利用 Linq 的水合 sproc 对象,这些对象对于使用 lambda 表达式评估结果非常方便。

但是 ToList() 需要非常非常长的时间来为这么多数据构建每个结果。如果我在那段时间暂停该过程,我可以看到它只是一遍又一遍地循环通过 sproc 的构造函数。查看我的网络流量似乎可以确认每个对象的代码都将返回到数据库。将 DeferredLoadingEnabled 设置为 false 没有帮助。

有趣的是,我认为存储过程的一个缺点是它们会立即将所有数据转储给您,而不是作为 IQueryable?

4

3 回答 3

2

我认为您正在尝试以一种不是最佳的方式解决问题。如果您想提供仪表板报告,您应该有后台进程(可能是 sql 代理作业或 Windows 服务)构建物化仪表板表,其中将数字压缩成更小的“报告 dto”,然后您可以查询并放入仪表板。我不在乎 SQL 是什么,每个请求提取 100k 条记录,然后执行一些计算/处理以以有意义的方式显示该数据将是浪费且执行速度较慢。

于 2013-05-02T17:17:31.857 回答
0

在获取记录时尝试执行 TOList()。这可能会很快奏效。 var query = dbml.FooBar(OneParam, TwoParam, ThreeParam).Tolist();并直接使用该集合

 ReportGenerator.PivotTable(query);
 ReportGenerator.Chart(query);
于 2013-05-02T05:09:30.673 回答
0

我的解决方案是使用老式的 ADO.NET 来查询存储的过程。显然不像 L2S 那样简单,但在这种情况下,它的速度比 L2S 快得多,它似乎为每一行运行该过程。

public List<object> Foo(SqlConnection connection)
{
    var query = "[dbo].[FooBar]";
    var command = new SqlCommand(query, connection);
    command.CommandType = CommandType.StoredProcedure;
    connection.Open();

    var reader = command.ExecuteReader();
    var results = new List<object>(); // Or whatever type your data is.

    while (reader.Read())
    {
        // Make this work for your particular data structure:
        results.Add(reader.GetString(0));
    }

    connection.Close();

    return results;
}

为了安全起见,还要确保使用 using 语句创建连接:

using (var connection = new SqlConnection(connectionString))
{
    results = Foo(connection);
}

ReportGenerator.PivotTable(results);
ReportGenerator.Chart(results);
//etc.
于 2014-05-05T22:56:06.753 回答