views:

34

answers:

3

My applications runs queries against a sql server database.

In many cases I can see the benefit of an execution plan: for example I click for the first time on a button to

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

it takes 15 seconds the first time, 8 seconds the following times.

EDIT: I USE PARAMETRIZED QUERIES.

So I have a 7 seconds improvement the second time.

Now as I run the application again (so I do a new database connection) the first time it will take 15 seconds, the second time 7...

How is it possible to tell SQL Server to store the execution plans, at least to remember them for same days? Or however how can I get benefit of already calculated execution plans? If different users run the same query is it a way to tell sql server to be smart enough to use the same execution plan, even if in that case probably the IdUser will be different.

In software I have some parameters, so may be the next execution of the query will have different MinDate and MaxDate, but will this affect the query plan?

+2  A: 

Use parametrised queries to maximise the chances that the plan will be cached

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

SQL Server does do auto parametrisation but can be quite conservative about this.

You can get some insight into plan reuse from the following

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'
Martin Smith
I use parametrized queries, I run them from Delphi application that through OLEDB passes a parametrized query to the server.
@user - What do you get when you run the query in my answer?
Martin Smith
+2  A: 

SQL Server will do this for you - any execution plan is stored for as long as there is space available.

However, you can do a lot to increase the chances of execution plans being stored and reused - what you need to take care is to create identical SQL queries - anything down to an extra space can cause SQL Server to consider two queries to be different and not reuse an existing query plan.

So therefore:

  • be consistent in your queries - always spell out things in identical manner (watch out for capitalization / non-capitalization, whitespaces, dbo. prefixes etc.)

  • use parameters instead of literal values; if you use literal values your query plans will not be reused, and they unnecessarily fill up the plan cache.

  • try to avoid SELECT * - this means the query optimizer has less options - since you want all columns, it typically has to do a scan on the clustered index. If you specify the three, five, six columns you really need, there's a chance there might be an index that covers the query (contains all the columns you're interested in) and therefore, the query analyze could use that index and do an index scan / index seek on that (and reuse that plan).

So instead of your SQL now, use this instead:

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

That should increase query plan reuse significantly.

marc_s
Ok, I do like this, but I notice an improvement only inside the same program execution. What I am trying to achieve is to use the execution plan in 2 different executions of the application. Or are execution plans linked to a specific session?
@user - No. As long as the `SET` options are the same the plan should be shared.
Martin Smith
@Martin Smith - sorry what do you mean by SET options?
@user - Things like `SET ARITHABORT ON` See table3 here for a full list http://msdn.microsoft.com/en-us/library/ee343986%28SQL.100%29.aspx
Martin Smith
A: 

Have you run the SQL Server Profiler? If so, are you sure the extra time is taken in compiling the statement and generating execution plans?

From your problem description, the additional 7 seconds could be time to setup the initial connection to the database. Maybe you've ruled this out already. I don't know.

An additional concern is the data cache. The first time you access data, SQL Server loads it into its cache. This can reduce the time of subsequent queries (assuming it can hold all the data).

Paul Williams
no i am always connected. Pressing the button refreshes a gird and runs a query, doesn't perform the connection. Anyway when I measured this I was creating some dummy indexes to force the recreation of the query plan.