.net - 在 SSMS 中快,在应用程序中慢 - 为什么这个数据集需要这么长时间才能填充?

标签 .net sql ado.net dataset

我有一个数据集,它是通过查询填充的,如下所示...

SELECT  DISTINCT ColA, ColB, ColC, ColD, ColE, ColF, dbo.CustomFunction(ColA) AS ColG
FROM    TableA
    JOIN ViewA ON ColA = ViewColA 
WHERE   ColB = @P1 AND ColC = @P2 AND ColD = @P3 AND ColE = @P4 
ORDER BY ColB, ColC DESC, ColA

(查询字段等已混淆)

我已经分析了这个查询,它在 SSMS 中运行 12 秒内返回大约 200 行。请注意,我重新启动了服务器并使用了所需的 DBCC 命令来确保未使用现有的执行计划。

但是,当我从 .Net 应用程序运行此查询时,填充数据集需要超过 30 秒的时间,并且默认 ADO.Net 命令超时为 30 秒。

如果查询在 12 秒内运行,我只是不明白为什么需要超过 18 秒才能将 200 行填充到数据集中。除非这里发生了我不知道的事情。我想 ADO.Net 只是调用查询、获取数据并填充它。

人口代码如下所示(注意我是从另一个开发人员那里继承的)...

DataSet res = new DataSet();

    try
    {
        using (SqlDataAdapter da = new SqlClient.SqlDataAdapter())
        {
            var cmd = new SqlClient.SqlCommand();
            String params = FillParameters(cmd, _params, params);
            cmd.CommandText = params + SQL;
            cmd.Connection = conn;
            cmd.Transaction = _transaction;

            if (CommandTimeout.HasValue)
            {
                cmd.CommandTimeout = CommandTimeout.Value;
            }

            da.SelectCommand = cmd;
            da.Fill(res);
            return res;
        }
    }
    catch
    {
        throw;
    }

在调试中运行此方法,当调用 fill 方法时,该方法大约需要 50 秒才能完成。这可以通过在 ADO.Net 命令上设置较高的超时来证明。我对查询的性能感到满意,我可以在大约 12 秒内一致运行,那么为什么需要额外的 18 秒以上来填充数据集呢?

ADO.Net 是否对此代码执行了某些操作(可能是由于其结构),这意味着填充数据集需要超过 18 秒的时间?我尝试将 EnforceConstraints 设置为 false,但这没有什么区别。

需要注意的一点是,由于该程序的设计,sql 命令中输入的参数数量超过了所需的数量。 FillParameters 方法执行此操作。有 20 个左右的“默认”参数添加到命令中,但仅例如此查询使用了 4 个。

总而言之,

  • 可能发生了什么导致填充 DS 需要 18 秒以上?

  • ADO.Net 是否对我的数据集做了一些“聪明”的事情,而不仅仅是运行查询并填充数据集?

  • 是否是传入的参数过多导致了问题。

谢谢。

最佳答案

问题在于现有代码强制执行可序列化隔离级别。

我使用 SQL Server Profiler 比较了通过 SSMS 运行的查询和应用程序的命令和执行统计信息。

--- SSMS ---
....
....
set transaction isolation level read committed

CPU: 7797
Reads: 338,425
Writes: 1685
Duration: 7,912

--- Application ---
....
....
set transaction isolation level serializable 

CPU: 46,531
Reads: 241,202
Writes: 0
Duration: 46,792

然后,我使用设置事务隔离级别可序列化exec sp_executesql在 SSMS 中运行查询,以便 SQL Server 不会从 SSMS 获得有关查询包含的内容的提示。

这在 SSMS 和应用程序中重现了 30 秒以上的执行时间。

这只是修改代码以使用已提交读隔离级别的情况。

引用文献: http://www.sommarskog.se/query-plan-mysteries.html#otherreasons

关于.net - 在 SSMS 中快,在应用程序中慢 - 为什么这个数据集需要这么长时间才能填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9177343/

相关文章:

c# - MySQL - Entity Framework 的问题

.net - 数据表选择与 LINQ 选择

sql - 在 VARCHAR 数据库字段上建立索引可以提高插入速度吗?

SQL 多列索引不适用于 LIKE 查询

orm - 老式 SQL DB 访问与 ORM(NHibernate、EF 等)。谁赢?

c# - 以动态/编程方式将 WHERE 子句添加到 SQL

c# - 如何使用 OpenXML SDK 获取应用格式(格式化单元格值)的单元格值

c# - 批量更新字典内多个记录的属性 (VB.NET/C#)

.net - ASP.NET MVC 和 ADO.NET Entity Framework 中的最佳实践实体验证

c# - 为什么我的 SQL 查询在转换后比较日期时选择所有行?