我的应用程序针对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,但这会影响查询计划吗?
答案 0 :(得分: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'
答案 1 :(得分:2)
SQL Server将为您执行此操作 - 只要有可用空间,就会存储任何执行计划。
但是,您可以做很多事情来增加执行计划的存储和重用机会 - 您需要注意的是创建相同的 SQL查询 - 任何可能导致额外空间的事情都可能导致SQL Server认为两个查询不同,不重用现有的查询计划。
因此:
在您的查询中保持一致 - 始终以相同的方式拼写事物(注意大写/非大写,空格,dbo.
前缀等。)
使用参数而不是文字值;如果您使用文字值,您的查询计划将不会被重复使用,并且它们会不必要地填满计划缓存。
尽量避免SELECT *
- 这意味着查询优化器的选项较少 - 因为您需要所有列,它通常必须对聚簇索引进行扫描。如果指定了您真正需要的三列,五列,六列,则可能存在覆盖查询的索引(包含您感兴趣的所有列),因此查询分析可以使用该索引并执行索引扫描/索引寻求(并重用该计划)。
现在不用你的SQL,而是使用它:
SELECT (list of fields)
FROM dbo.MYTasks
WHERE DATE < @EndDate and DATE > @StartDate
这应该会显着增加查询计划的重用。
答案 2 :(得分:0)
您是否运行过SQL Server Profiler?如果是这样,您确定在编译语句和生成执行计划时会花费额外的时间吗?
从您的问题描述中,额外的7秒可能是设置与数据库的初始连接的时间。也许你已经排除了这一点。我不知道。
另一个问题是数据缓存。第一次访问数据时,SQL Server将其加载到其缓存中。这可以减少后续查询的时间(假设它可以保存所有数据)。