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.
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 some long running (a few hours) stored procedures which contain queries that goes to tables that contain millions of records in a distributed environment. These stored procedures take a date parameter and filters these tables according to that date parameter.
I've been thinking that because of the parameter sniffing feature of SQL Server, at the first time that my stored procedure gets called, the query execution plan will be cached according to that specific date and any future calls will use that exact plan. And I think that since creating an execution plan takes only a few seconds, why would I not use RECOMPILE option in my long running queries, right? Does it have any cons that I have missed?
if the query should run within your acceptable performance limits and you suspect parameter sniffing is the cause,i suggest you add recompile hint to the query..
Also if the query is part of stored proc,instead of recompiling the entire proc,you can also do a statement level recompilation like
create proc procname
(
#a int
)
as
select * from table where a=#a
option(recompile)
--no recompile here
select * from table t1
join
t2 on t1.id=t2.id
end
Also to remind ,recompiling query will cost you.But to quote from Paul White
There is a price to pay for the plan compilation on every execution, but the improved plan quality often repays this cost many times over.
Query store in 2016 helps you in tracking this issues and also stores plans for the queries over time..you will be able to see which are performing worse..
if you are not on 2016,William Durkin have developed open query store for versions (2008-2014) which works more or less the same and helps you in troubleshootng issues
Further reading:
Parameter Sniffing, Embedding, and the RECOMPILE Options
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.
I am trying to resolve a 100% cpu usage by the SQL Server process on the database server. While investigating, I have now come across the fact that the stored procedures are taking the most worker time.
For the following query of dmv's to find queries taking highest time,
SELECT TOP 20 st.text
,st.dbid
,st.objectid
,qs.total_worker_time
,qs.last_worker_time
,qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_worker_time DESC
most of them are stored procedures. The weird thing is that all these stored procedures are querying different tables. And yet they are the top of taking the most worker time, even though when I look at the Profiler for queries with top CPU, Reads, Duration, the stored procedures don't figure at the top there.
Why could this be happening?
==Edit==
The application actually uses adhoc queries more than stored procedures. Some of these procedures are to be migrated to using adhoc queries. The thing is that these procedures are not called as often as some of the other queries, which are cpu intensive, and are called very frequently.
Also, it does strike me odd that a stored procedure with which does a simple select a,b,c from tbl where id=#id would have a higher total worker time than a query which has mulitple joins, user defined functions in the where clause, a sort and a row_number over and while the simple one queries a table with 20000 records, the complex query is on a table with over 200,000 records.
It depends what are you doing in that stored procedure, how you are tuning your tables, indexes, etc.
For example if you create a stored procedure using loops like cursor you will have at maximum your cpu usage. If you don't setup your indexes and you are using select using different joins,etc. You'll have your cpu overloaded.
It is accordingly of how you use your database.
Some tips:
I recommend create stored procedure most of the time.
When you create your stored procedures, run with execution plan to get some suggestions.
If the tables have a lot of records (more than 1 or 2 millions), think about create index views.
Do update or delete only when is necessary, sometimes is better only insert records and run a job daily or weekly to update or remove the records that you don't need. (it depends of the case)
I have a query that has been running every day for a little over 2 years now and has typically taken less than 30 seconds to complete. All of a sudden, yesterday, the query started taking 3+ hours to complete and was using 100% CPU the entire time.
The SQL is:
SELECT
#id,
alpha.A, alpha.B, alpha.C,
beta.X, beta.Y, beta.Z,
alpha.P, alpha.Q
FROM
[DifferentDatabase].dbo.fnGetStuff(#id) beta
INNER JOIN vwSomeData alpha ON beta.id = alpha.id
alpha.id is a BIGINT type and beta.id is an INT type. dbo.fnGetStuff() is a simple SELECT statement with 2 INNER JOINs on tables in the same DB, using a WHERE id = #id. The function returns approximately 11000 results.
The view vwSomeData is a simple SELECT statement with two INNER JOINs that returns about 590000 results.
Both the view and the function will complete in less than 10 seconds when executed by themselves. Selecting the results of the function into a temporary table first and then joining on that makes the query finish in < 10 seconds.
How do I troubleshoot what's going on? I don't see any locks in the activity manager.
Look at the query plan. My guess is that there is a table scan or more in the execution plan. This will cause huge amounts of I/O for the few record you get in the result.
You could use the SQL Server Profiler tool to monitor what queries are running on SQL Server. It doesn't show the locks, but it can for instance also give you hints on how to improve your query by suggesting indexes.
If you've got a reasonably recent version of SQL Server Management Studio, it has a Database Tuning Adviser as well, under Tools. It takes a trace from the Profiler and makes some, sometimes highly useful, suggestions. Makes sure there's not too many queries - it takes a long time to build advice.
I'm not an expert on it, but have had some luck with it in the past.
Do you need to use a function? Can you re-write the entire thing into a stored procedure in which you pass in the #ID as a parameter.
Even if your table has indexes because you pass the #ID as a variable to the WHERE clause potentially greatly increasing the amount of time for the query to run.
The reason the indexes may not be used is because the Query Analyzer does not know the value of the variables when it selects an access method to perform the query. Because this is a batch file, only one pass is made of the Transact-SQL code, preventing the Query Optimizer from knowing what it needs to know in order to select an access method that uses the indexes.
You might want to consider an INDEX query hint if you cannot re-write the SQL.
it might also be possible, since this just started happening, that the INDEXes have become fragmented and might need to be rebuilt.
I've had similar problems with joining functions that return large datasets. I had to do what you've already suggested. Put the results in a temp table and join on that.
Look at the estimated plan, this will probably shed some light. Typically when query cost gets orders of magnitude more expensive it is because a loop or merge join is being used where a hash join is more appropriate. If you see a loop or merge join in the estimated plan, look at the number of rows it expects to process - is it far smaller than the number of rows you know will actually be in play? You can also specify a hint to use a hash join and see if it performs much better. If so, try updating statistics and see if it goes back to a hash join without a hint.
SELECT
#id,
alpha.A, alpha.B, alpha.C,
beta.X, beta.Y, beta.Z,
alpha.P, alpha.Q
FROM
[DifferentDatabase].dbo.fnGetStuff(#id) beta
INNER HASH JOIN vwSomeData alpha ON beta.id = alpha.id
-- having no idea what type of schema is in place and just trying to throw out ideas:
Like others have said... use Profiler and find the source of pain... but I'm thinking it is the function on the other database. Since that function might be a source of pain, have you thought about a little denormalization or anything on [DifferentDatabase]. I think you'll find a bit more scalability in joining to a more flattened table with indexes than a costly function.
Run this command:
SET SHOWPLAN_ALL ON
Then run your query. It will display the execution plan, look for a "SCAN" on an index or a table. That is most likely what is happening to your query now. If that is the case, try to figure out why it is not using indexes now (refresh statistics, etc)