【问题标题】:ADO.Net, Parametrized Queries and Plan CachingADO.Net,参数化查询和计划缓存
【发布时间】:2013-06-25 03:23:46
【问题描述】:

如果我有一个使用 ADO.Net 连接到 SQL Server 2008 R2 并使用即席参数化查询来检索数据的桌面应用程序,那么当应用程序的两个不同实例运行查询时会发生什么情况?第一个调用是否被编译,第二个调用是否使用内存版本?

查询示例:

SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s = "SELECT email, passwd, login_id, full_name " + 
  "FROM members WHERE email = @email";
SqlCommand cmd = new SqlCommand(s);
cmd.Parameters.Add("@email", email);
SqlDataReader reader = cmd.ExecuteReader();

我注意到第一次触发查询时查询性能很慢,并且连续调用似乎很好。我只是想知道这是否是应用程序每个实例的全面行为,或者如果第一次从一个实例触发查询,它会提高使用此查询的所有应用程序实例的性能。

【问题讨论】:

    标签: sql-server performance sql-server-2008 ado.net


    【解决方案1】:

    SQL Server 必须在第一次获取查询时对其进行分析,并为它找到一个性能相当好的执行计划。

    完成后,查询

    SELECT email, passwd, login_id, full_name FROM members WHERE email = @email
    

    其执行计划存储在计划缓存中。

    只要计划缓存有足够的空间,那么该完全相同查询的任何后续执行(“相同”到最后一个逗号、空格或任何东西!它必须绝对相同的 SQL)将从计划缓存中重用该执行计划。

    所以是的 - 第一次执行查询时(例如,在 SQL Server 重新启动后),会有轻微的延迟,但一旦执行并缓存了查询计划,它应该会执行得更好 - 对于 所有连接到将使用完全相同的查询的 SQL Server。

    对完全相同的查询的要求也说明了为什么它如此糟糕 - 也是从性能的角度来看 - 自己将 SQL 串在一起并将查询值放入实际的查询文本中 - 这样,每个查询都有新的值是一个新的 SQL 查询文本,并且对于每个请求都必须重复整个故事。如果您像您一样使用 参数化 查询,则查询保持不变,因此可以重用缓存的执行计划 - 只有参数值更改,但这不会影响查询执行计划以及重用缓存计划的能力

    【讨论】:

    • 感谢您的回复。关闭为我继承的这个应用程序创建存储过程。
    【解决方案2】:

    我认为编译和计划缓存在这里无关紧要(您的 SQL 请求是微不足道的)。更重要的是磁盘缓存。看来,第一次从磁盘进行物理读取,下一次进行逻辑读取(从缓冲区缓存)。此磁盘缓存是服务器范围的。

    你可以试试添加命令

    DBCC DROPCLEANBUFFERS
    

    在您请求之前,强制清理磁盘缓存。所以你可以检查性能

    【讨论】:

      【解决方案3】:

      是的,参数化的查询执行计划被兑现并为每个连接重复使用,直到它们从兑现中被推送。您可以使用事件SP:Recompile 检查计划是否在 Profiler 中重新编译。更多相关内容你可以阅读 MSDN 文章Execution Plan Caching and Reuse

      但是,在您的情况下,我认为更重要的作用是兑现数据。只要您在第一次将数据页面加载到 RAM 时执行查询,并一直停留在那里,直到它们从 Cashe 中被推送。如果它们将相同的值传递给@email 参数或者您在字段email 上没有索引(或两者都有),它可能会影响后续查询的执行时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        相关资源
        最近更新 更多