【问题标题】:Get the execution time of a ADO.NET SQL Command获取 ADO.NET SQL 命令的执行时间
【发布时间】:2017-03-23 08:41:40
【问题描述】:

我一直在寻找是否有任何简单的方法可以获取 ADO.NET 命令对象的执行时间。

我知道我可以手动启动和停止秒表。但是想在 ADO.NET 中是否有任何简单的方法来做到这一点

【问题讨论】:

  • 您想要查询的执行时间,还是包括将数据返回到 c# 的整个时间?
  • 你想做什么? SQL Server 已经允许您通过扩展事件以最低成本收集此类数据。收集单个查询的统计数据可能很有趣,但对于性能监控或故障排除不是很有用

标签: c# .net sql-server performance ado.net


【解决方案1】:

有一种方法,但使用SqlConnection,而不是命令对象。示例:

using (var c = new SqlConnection(connectionString)) {
    // important
    c.StatisticsEnabled = true;
    c.Open();
    using (var cmd = new SqlCommand("select * from Error", c)) {
        cmd.ExecuteReader().Dispose();
    }       
    var stats = c.RetrieveStatistics();
    var firstCommandExecutionTimeInMs = (long) stats["ExecutionTime"];
    // reset for next command
    c.ResetStatistics();
    using (var cmd = new SqlCommand("select * from Code", c))
    {
        cmd.ExecuteReader().Dispose();
    }
    stats = c.RetrieveStatistics();
    var secondCommandExecutionTimeInMs = (long)stats["ExecutionTime"];
 }

Here你可以找到RetrieveStatistics返回的字典中包含的其他值。

请注意,这些值代表 客户端 统计信息(基本上是 ADO.NET 内部测量它们),但您似乎要求Stopwatch 的模拟 - 我认为这很好。

【讨论】:

    【解决方案2】:

    answer of @Evk 的方法非常有趣和聪明:它在 客户端 端工作,而此类统计数据的主要关键之一实际上是 NetworkServerTime,其中

    返回累积的时间量(以毫秒为单位) 提供者花费了等待服务器的回复一次 应用程序已开始使用提供程序并启用了统计信息。

    所以它包括从 DB 服务器到 ADO NET 客户端的网络时间。

    另一种更面向数据库服务器的方法是运行SET STATISTICS TIME ON,然后检索InfoMessage

    委托的代码草稿(我只是写到调试控制台,但你可能想用StringBuilderAppend替换它)

    internal static void TrackInfo(object sender, SqlInfoMessageEventArgs e)
    {
        Debug.WriteLine(e.Message);
        foreach (var element in e.Errors) {
            Debug.WriteLine(element.ToString());
        }
    }
    

    和用法

    conn.InfoMessage +=  TrackInfo;
    using (var cmd = new SqlCommand(@"SET STATISTICS TIME ON", conn)) {
        cmd.ExecuteNonQuery();
    }
    using (var cmd = new SqlCommand(yourQuery, conn)) {
        var RD = cmd.ExecuteReader();
        while (RD.Read()) {
            // read the columns
        }
    }
    

    【讨论】:

    • StatisticsEnabled 开关不也是这样吗?返回服务器端统计数据?
    • @PanagiotisKanavos 不,实际上我已经复制了其中一个键的定义以显示差异,如果您查看ExecutionTime,则相同...另一个答案中的统计数据是客户端(意思是 ADO.NET 提供者)端
    • @PanagiotisKanavos 是的,这些是客户端统计信息。作者要求使用Stopwatch 进行手动测量的模拟,所以看起来很合适。
    • 在服务器上,我会使用扩展事件并将其设置为从 all 查询中收集性能统计信息。成本最低(与旧的 Profiler 不同),存储目标可以是内存或文件。可以添加持续时间和 IO 等过滤条件来仅捕获特定事件,例如频繁的慢速查询、不频繁的重度查询。
    【解决方案3】:

    我建议您迁移到 SQL Server 2016 并使用 Query Store 功能。这将跟踪您提交的每个查询的执行时间和性能随时间的变化。无需更改您的应用程序。跟踪所有查询,包括在存储过程中执行的查询。跟踪任何应用程序,而不仅仅是您自己的。适用于所有版本,包括 Express 和 Azure SQL DB 服务。

    如果您在客户端进行跟踪,您必须自己使用挂钟测量时间。我会添加并公开performance counters,然后使用性能计数器基础架构来捕获和存储测量结果。

    另一方面,简单地跟踪发送到 SQL Server 的批处理的执行时间会产生非常粗略的性能信息并且很少可操作。阅读How to analyse SQL Server performance

    【讨论】:

    • 这并不比简单地检索执行的统计信息容易
    • 此外,您可以使用扩展事件和 DMV 获取此类统计信息。可以使用 SQL Server Utility 或 Management Warehouse 来收集和测量性能。查询存储服务器的目的不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    相关资源
    最近更新 更多