4

我的应用程序针对 sql server 数据库运行查询。

在许多情况下,我可以看到执行计划的好处:例如,我第一次单击按钮

SELECT * from Tasks
WHERE IdUser = 24 AND
  DATE < '12/12/2010' and DATE > '01/01/2010'

第一次需要 15 秒,以后需要 8 秒。

编辑:我使用参数化查询。

所以我第二次提高了 7 秒。

现在,当我再次运行应用程序时(所以我进行了新的数据库连接),第一次需要 15 秒,第二次需要 7...

怎么可能告诉 SQL Server 存储执行计划,至少在同一天记住它们?或者,我怎样才能从已经计算好的执行计划中获益?如果不同的用户运行相同的查询,这是告诉 sql server 足够聪明以使用相同的执行计划的一种方式,即使在这种情况下 IdUser 可能会有所不同。

在软件中我有一些参数,所以可能下次执行查询会有不同的MinDate和MaxDate,但这会影响查询计划吗?

4

3 回答 3

2

使用参数化查询来最大化计划被缓存的机会

SELECT * from MYTasks 
WHERE IdUser = @UserId AND DATE < @enddate and DATE > @startdate

SQL Server 确实进行了自动参数化,但对此可能非常保守。

您可以从以下内容中深入了解计划重用

SELECT usecounts, cacheobjtype, objtype, text, query_plan, value as set_options
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 
cross APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
where text like '%MYTasks%' and attribute='set_options'
于 2010-09-02T16:05:42.633 回答
2

SQL Server 将为您执行此操作 - 只要有可用空间,就会存储任何执行计划。

然而,你可以做很多事情来增加执行计划被存储和重用的机会——你需要注意的是创建相同的 SQL 查询——任何额外的空间都可能导致 SQL Server 认为两个查询是不同的,并且不重用现有的查询计划。

因此:

  • 在您的查询中保持一致 - 始终以相同的方式拼写事物(注意大写/非大写、空格、dbo.前缀等)

  • 使用参数而不是文字值;如果您使用文字值,您的查询计划将不会被重用,并且它们会不必要地填满计划缓存。

  • 尽量避免SELECT *——这意味着查询优化器的选项更少——因为你想要所有的列,它通常必须对聚集索引进行扫描。如果您指定了您真正需要的三、五、六列,则可能存在一个涵盖查询的索引(包含您感兴趣的所有列),因此,查询分析可以使用该索引并执行索引扫描/索引搜索(并重用该计划)。

因此,现在不要使用您的 SQL,而是使用它:

SELECT (list of fields)
FROM dbo.MYTasks 
WHERE DATE < @EndDate and DATE > @StartDate

这应该会显着增加查询计划的重用。

于 2010-09-02T16:06:10.097 回答
0

您是否运行过 SQL Server Profiler?如果是这样,您确定编译语句和生成执行计划会花费额外的时间吗?

根据您的问题描述,额外的 7 秒可能是设置与数据库的初始连接的时间。也许你已经排除了这一点。我不知道。

另一个问题是数据缓存。第一次访问数据时,SQL Server 会将其加载到其缓存中。这可以减少后续查询的时间(假设它可以保存所有数据)。

于 2010-09-02T16:28:50.930 回答