I am developing a .NET program to retrieve execution plans of all stored procedures in a given database. I am going to parse these XML's at program side.
SET SHOWPLAN_XML ON and execute the procedure gives the plan. However, the problem is that all the parameters of the procedure needs to be passed.
Is there any way to retrieve execution plan without passing any parameters of the stored procedure, by giving the name of the procedure only?
Yes, you probably want to take a look at the plan cache - SQL Server caches all execution plans and allows you to take a look at them using DMVs. For example the following is a basic query which will list all cached query plans (as xml) along with their SQL text. On most database you will also need to add additional filtering clauses to filter the results down to just the plans you are interested in.
SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
Note that these plans only include the estimated execution plan and won't contain the "actual" values (e.g. actual number of reads). Also you can't use this to get the query plan for an encrypted stored procedure.
See also How do I obtain a Query Execution Plan?, also Tools for visualising execution xml plans as HTML may be useful for the "parsing the XML" part.
Related
Our team has assigned a new task to me to look into the performance of a huge stored procedure. When I observe in the development environment with the proper data I have noticed that the procedure takes a considerable time to execute. In my scenario it took around 45 minutes. There are multiple INSERT/DELETE/UPDATE queries are used in the stored procedure. But I am unable to get which query is causing the issue. The data volume which is used in the queries are also pretty less.
How can I pinpoint to the exact query in the stored procedure
which is getting executed?
My Server version is SQL Server 2008 R2.
There are couple of ways to find out the query which is executing as part of a stored procedure. Learn more about DMVs and SQL Profiler. Both will give you an oversight to pinpoint the queries that are being used in a stored procedure.
In SQL Profiler, use the SP:StmtCompleted or SP:StmtStarting to include the statements inside the query. But I would advice not to go with the Profiler as it affects the system memory as well. Also it may give you unwanted additional information as well.
The best way is to use DMV (Dynamic Management Views). If you know the process id (SPID) use the below query to find out the query
The first query will give you the details about the stored procedures and the second will give you the exact query which is currently executing. Replace the SPID in the below query with the corresponding SPID of your process.
SELECT requests.session_id,
requests.status,
requests.command,
requests.statement_start_offset,
requests.statement_end_offset,
requests.total_elapsed_time,
details.text
FROM sys.dm_exec_requests requests
CROSS APPLY sys.dm_exec_sql_text (requests.sql_handle) details
WHERE requests.session_id = SPID
ORDER BY total_elapsed_time DESC
SELECT SUBSTRING(detail.text,
requests.statement_start_offset / 2,
(requests.statement_end_offset - requests.statement_start_offset) / 2)
FROM sys.dm_exec_requests requests
CROSS APPLY sys.dm_exec_sql_text (requests.sql_handle) detail
WHERE requests.session_id = SPID
Once you have done identifying the queries which is causing slowness, you can use Actual execution plan to identify the issues in the query.
Try this and please comment whether it is working for you.
I have then following tracert about one query in my application:
As you can see, the query reads all registers in the table and the result is a big impact in time duration.
But when I try to execute the query directly the result is another... What is wrong?
You executed ANOTHER query from SSMS.
The query shown in profiler is part of stored procedure, and has 8 parameters.
What you've executed is a query with constants that has another execution plan as all the constants are known and estimation was done in base of these known values.
When your sp's statement was executed the plan was created for god-knows-what sniffed parameters and this plan is different from what you have in SSMS.
From the thikness of arrows in SSMS it's clear that you query does not do 7.954.449 reads.
If you want to see you actual execution plan in profiler you should select corresponding event (Showplan XML Statistics Profile ).
Yes, There are two different queries. The Axapta uses placeholders in common. Your query uses literal constants.
The forceLiterals hint in the query make the Axapta query similar to your SSMS sample. Default Axapta hint is forcePlaceholders.
Main goal of placeholders is optimize a massive stream of similar queries with different constants from multiple clients. Mainly due to the use of a query plans cache.
see also the injection warning for forceLiterals:
https://msdn.microsoft.com/en-us/library/aa861766.aspx
I have a stored procedure which is contains a lot of query.
I Would like to execute the query plan only for a specific query.
EX:
select * from A
select * from B
--QUERY PLAN THIS
select * from C
--END OF QUERY PLAN
select * from D
Thanks a lot
You really can't do that. So you have to work around the problem by extracting that specific bit of SQL and building its execution plan by itself.
It may be that you're curious to see if the execution plan is affected when running in the context of the rest of the stored procedure. In that case you'll have to go ahead and generate a plan on the whole procedure and decipher what piece of it is the query you're concerned with.
You may also find SQL profiler helpful when trying to optimize/troubleshoot specific elements of complicated procedures.
I completed my project, there are many procedures used and now I got the job to find the mostly used procedure and there average execution time.
In this way I know what are the procedures I need to tune first?
It there any way to get procedure execution history for a particular database?
I believe you can use the sys.dm_exec_query_stats dynamic management view. There are two columns in this view called execution_count, and total_worker_time that will help you.
execution_count gives the total number of times the stored procedure in question was executed since the last time it was recompiled.
total_worker_time gives the total CPU time in milliseconds that was spent executing this stored procedure since the last time it was recompiled.
Here is an MSDN link:
http://msdn.microsoft.com/en-us/library/ms189741.aspx
You can use dm_exec_cached_plans to look for the stored procedures that have been compiled into query plans. The function dm_exec_query_plan can be used to retrieve the object id for a plan, which in turn can be translated into the procedure's name:
select object_name(qp.objectid)
, cp.usecounts
from sys.dm_exec_cached_plans cp
cross apply
sys.dm_exec_query_plan(cp.plan_handle) qp
where cp.objtype = 'Proc'
order by
cp.usecounts desc
I think you want to check SQL Server Profiler for this.
You can check the details in MSDN and other places as well.
But, before using it in production server, you need to keep in mind that:
Profiler adds too much overhead to production server. So, first check when your site has less no of hits, and go ahead.
This is what the SQL Server Profiler is for. With it you can keep track of query run count, execution time, etc.
Can any body help me in understanding if the execution plan for functions cached in SQL server?
Any online resource for this?
The accepted answer is inaccurate / misleading, primarily due to the referenced quote being too vague with regards to the term "user-defined functions".
There are several different types of User-Defined Functions in Microsoft SQL Server, and they are treated differently:
Multi-statement TVFs:
These are treated like Stored Procedures. The query that executes them only shows the reference to their name, not to any of their definition. They show up in sys.dm_exec_cached_plans with a cacheobjtype of "Compiled Plan" and an objtype of "Proc". Any input parameter values are also stored with the plan, hence Multi-statement TVFs are subject to parameter-sniffing issues.
Inline TVFs (iTVFs):
These are treated like Views. The query that executes them incorporates their definition. They show up in sys.dm_exec_cached_plans with a cacheobjtype of "Parse Tree" and an objtype of "View". Input parameter values are not stored with the plan, hence Inline TVFs are not subject to parameter-sniffing issues.
Scalar UDFs:
These are treated like Stored Procedures. The query that executes them only shows the reference to their name, not to any of their definition. They show up in sys.dm_exec_cached_plans with a cacheobjtype of "Compiled Plan" and an objtype of "Proc". Any input parameter values are also stored with the plan, hence Scalar UDFs are subject to parameter-sniffing issues. Also, unlike the two types of TVFs noted above, but like regular Stored Procedures, you can force recompilation of the execution plan using the WITH RECOMPILE option when executing via EXEC[UTE] instead of SELECT or SET.
SQLCLR objects:
These are treated more like client / app code. The query that executes them only shows the reference to their name, not to any of their definition. They show up in sys.dm_exec_cached_plans with a cacheobjtype of "CLR Compiled Func" or "CLR Compiled Proc", and an objtype of "Proc". But, unlike Multi-statement TVFs and Scalar UDFs, they do not have a definition and so do not have an associated query plan. However, any adhoc queries (not stored procedure calls) that they execute show up in sys.dm_exec_cached_plans with a cacheobjtype of "Compiled Plan" and an objtype of "Prepared". Any of these adhoc queries, if parameterized, should be storing the initial input parameter values with the prepared plan, and would hence be subject to parameter-sniffing issues.
For more details on object caching, please see the MSDN page on Caching Mechanisms.
Yes they do go in the execution plan cache.
The sys.dm_exec_query_plan DMV will show a plan for given plan handle. Quote from there:
Query plans for various types of
Transact-SQL batches, such as ad hoc
batches, stored procedures, and
user-defined functions, are cached in
an area of memory called the plan
cache. Each cached query plan is
identified by a unique identifier
called a plan handle. You can specify
this plan handle with the
sys.dm_exec_query_plan dynamic
management view to retrieve the
execution plan for a particular
Transact-SQL query or batch.
Yes they are considered for caching.
http://msdn.microsoft.com/en-us/library/ms181055.aspx