2

问题:

DateTime.Now作为参数传递给 proc 是否会阻止 SQL Server 缓存查询计划?如果是这样,那么 Web 应用程序是否错过了巨大的性能提升?

可能的解决方案:

我认为DateTime.Today.AddDays(1)这将是一个可能的解决方案。它会将相同的结束日期传递给 sql proc(每天)。并且用户仍然会得到最新的数据。请也谈谈这个。

给定示例:

假设我们有一个存储过程。它将数据报告给网页上的用户。用户可以设置日期范围。如果用户将今天的日期设置为“结束日期”,其中包括今天的数据,则 Web 应用程序将传递DateTime.Now给 sql proc。

假设一个用户多次运行报告5/1/2010--to-- now。在网页上,用户5/1/2010看到5/4/2010. 但是 Web 应用程序DateTime.Now作为结束日期传递给 sql proc。因此,过程中的结束日期总是不同的,尽管用户正在查询类似的日期范围。

假设表中的记录数和用户数很大。因此,任何性能提升都很重要。因此问题的重要性。

过程和执行示例(如果这有助于理解):

CREATE PROCEDURE GetFooData
    @StartDate datetime
    @EndDate datetime
AS

    SELECT *
    FROM Foo
    WHERE LogDate >= @StartDate
    AND LogDate < @EndDate

这是使用 DateTime.Now 的示例执行:

EXEC GetFooData '2010-05-01', '2010-05-04 15:41:27' -- passed in DateTime.Now

这是使用 DateTime.Today.AddDays(1) 的示例执行

EXEC GetFooData '2010-05-01', '2010-05-05' -- passed in DateTime.Today.AddDays(1)

两个过程返回相同的数据,因为当前时间是:2010-05-04 15:41:27

4

3 回答 3

6

无论参数值如何,查询计划都将被缓存。参数基本上保证存在一致的、可重用的查询,因为就 SQL 服务器而言它们是类型安全的。

您想要的不是查询计划,而是结果缓存。这将受到您描述的行为的影响。

由于您似乎只处理一整天,您可以尝试传入日期,而不是日期时间,以最小化不同的参数值。还可以尝试在应用程序中缓存查询结果,而不是每次都进行数据库往返。

于 2010-05-04T22:50:39.740 回答
1

因为您调用的是存储过程,而不是直接查询,所以您唯一更改的查询是您发送到 SQL 的实际批处理,即EXEC GetFooData '2010-05-01', '2010-05-05'vs. GetFooData '2010-05-01', '2010-05-04 15:41:27'. 这是一个微不足道的批处理,它将生成一个微不足道的计划。虽然从严格的技术角度来看,您正在失去一些性能,但这确实是无法衡量的。此响应中解释了为什么会发生这种情况的详细信息:Dynamicly created SQL vs Parameters in SQL Server

好消息是,通过对 SqlClient 调用代码进行微小更改,您将受益于其中提到的微小性能改进。将您的 SqlCommand 代码更改为显式存储过程调用:

SqlCommand cmd = new SqlCommand("GetFooData", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@StartDate", dateFrom);
cmd.Parameters.AddWithValue("@EndDate", DateTime.Now);

附带说明一下,在数据库中存储本地化时间不是一个好主意,因为客户端与服务器位于不同的时区,并且由于夏令时更改夜间的复杂性。更好的解决方案是始终存储 UTC 时间,并在应用程序中将其简单地格式化为用户的本地时间。

于 2010-05-05T01:18:52.063 回答
1

在您的情况下,如果第二个参数只是实时向上漂移,您可能没问题。

但是,有可能成为参数嗅探的受害者,其中第一次执行(产生缓存的执行计划)被调用的参数产生的计划通常不适用于通常使用的其他参数(或数据配置文件急剧变化) )。后面的调用可能会使用一个有时很差,甚至无法正确完成的计划。

如果您的数据配置文件因参数选择的不同而发生巨大变化,并且某些参数选择的执行计划变得很差,您可以将参数屏蔽为局部变量 - 这将有效地防止 SQL Server 2005 中的参数嗅探。 还有 WITH RECOMPILE (无论是在 SP 中还是在 EXEC 中——但对于被大量调用的 SP,这不是一个可行的选择)在 SQL Server 2008 中,我几乎总是使用 OPTIMIZE FOR UNKNOWN 这将避免产生基于参数嗅探的计划。

于 2010-05-05T03:52:16.303 回答