0

如果我有一个使用 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();

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

4

3 回答 3

2

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

完成后,查询

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

它的执行计划存储在计划缓存中。

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

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

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

于 2013-06-25T04:58:46.033 回答
0

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

您可以尝试添加命令

DBCC DROPCLEANBUFFERS

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

于 2013-06-25T05:07:04.243 回答
0

是的,参数化的查询执行计划被兑现并为每个连接重复使用,直到它们从兑现中被推送。您可以检查计划是否在 Profiler 中使用 event 重新编译SP:Recompile。有关它的更多信息,您可以在 MSDN 文章执行计划缓存和重用中阅读

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

于 2013-06-25T05:07:18.840 回答