AFAIK, you cannot force a plan to stay in cache. However, a query can be thrown out of the cache for several reasons. Read a blog about execution plans. It states some reasons why execution plans get invalidated:
- Changing the structure or schema of a table referenced by the query
- Changing an index used by the query
- Dropping an index used by the query
- Updating the statistics used by the query
- Calling the function, sp_recompile
- Subjecting the keys in tables referenced by the query to a large number of inserts or deletes
- For tables with triggers, significant growth of the inserted or deleted tables
- Mixing DDL and DML within a single query, often called a deferred compile
- Changing the SET options within the execution of the query
- Changing the structure or schema of temporary tables used by the query
- Changes to dynamic views used by the query
- Changes to cursor options within the query
- Changes to a remote rowset, like in a distributed partitioned view
- When using client side cursors, if the FOR BROWSE options are changed
Another pitfall could be that the query changes. This can happen if the where clause changes (e.g. you filter by date) and you don't use bind
Thinking about, you haven't stated that you checked whether the execution plan is still in cache or not. You should query the cache to figure that out. However, since you say your query runs only once a day, the plan might just be expired. The blog actually mentions the formula on how sql server determines when to expire a plan:
If the following criteria are met, the plan is removed from memory:
- More memory is required by the system
- The "age" of the plan has reached zero
- The plan isn't currently being referenced by an existing connection
In general, 7 seconds is not to bad if you have a big report. It takes longer to get a coffee. Does it create any other issue than 6 seconds of wasted productivity for an end user?