SQL Tuning
SQL Tuning
Table of Contents Overview..............................................................................................................................2 Introduction..........................................................................................................................3 Creating Query Lists with a SQL Profiler Trace ................................................................4 Long Running and New Queries......................................................................................5 Recompiling Queries.......................................................................................................8 Compilation Process..........................................................................................................10 Conclusion.........................................................................................................................12 Reference...........................................................................................................................12
SQL Performance Tuning Creating Query Lists with a SQL Profiler Trace
To create a lists of queries, you will need to create and run a trace capturing all the Stored Procedure events, as well as the following data columns: EventClass EventSubClass TextData CPU Reads Writes Duration SPID StartTime EndTime NestLevel ObjectID ObjectName ObjectType
This trace may create a large amount of data, so it might be easier to create the trace so it will place the information to a table so you can use a query to view the data. If can find a way to filter the trace in order to limit the data output, I would suggest that you do so. I usually start my stored procedure names with 'spXXXX' so I can filter by object name. But as you look into your particular situation, you can usually come up with something to use to filter some of the unneeded data out to lessen the impact of the trace and the amount of data you have to sift through. Now that you have trace data saved to a table. Create several stored procedures that you can use to identify the worst performing procedures by looking at duration (duration is displayed as milliseconds), SP:CacheMiss, SP:Recompile, Reads, and Writes. Create lists with the largest durations, the most Reads, the most Writes, and stored procedures that include the SP:CacheMiss and the SP:Recompile events. It might take you a few times to learn what is considered excessive Reads and Writes
Look at how you are obtaining the data from the tables. Is the query doing a Table Scan? Can you do anything to change the Index or Clustered Index Scans into Index or Clustered Index Seeks? Can you rework your query to use the Clustered Index instead of a Non-Clustered Index? Simply moving the base data retrieval from a Table Scan to an Index or Clustered Index seek will usually solve the problem of a slow-running query. This is a very quick way to improve the performance of a majority of the problem queries you will encounter.
Look at the Cost of each query segment. A simple thing to remember is that the Cost of each segment roughly equates to the percentage of time it takes that segment to complete. Look at the larger percentages and see if you can optimize that segment of code any. The result may still mean that the segment remains the most costly, but the goal is to optimize that segment so
Can you reduce the use of temporary tables or the TABLE data type in the query? While these objects have their uses, some developers have a habit of using them when they are not really needed. Ask yourself if a JOIN can be used instead or if a different WHERE clause will eliminate the need for the table. If you can't eliminate the table, see if you can reduce its size with filters or use a table permanently created in a database so you do not have to take the performance hit of creating the table each time it is needed.
Do you have any statements that modify table structures? Just as creating a temp table in a query, modify tables in queries also cause a performance hit. Look at ways to work around these statements. A generic table may be able to be created that will server your needs.
Does the query return more data than is needed? Network congestion can cause minor problems with stored procedures. Try not to return more data or columns than is needed by the application. Also try to use SET NOCOUNT ON to reduce the usually unneeded row count that is return by all queries.
Are you using the sp_executesql system stored procedure instead of the EXECUTE command to run strings? The sp_executesql system stored procedure has a slightly performance advantage over the EXECUTE command.
Have you created any transactions within the query? If you create transactions in your code, make sure you can estimate the cost of that transaction. By knowing the cost of the transaction, you can estimate if it will normally take 1 second, 1 minute, or 1 hour for the transaction to complete. Steps can then be taken to simplify the transaction if the estimated cost exceeds a few seconds. Otherwise, you run the chance of introducing very slow queries that might even cause database blocking problems because of the time needed for the transaction to complete.
Keep the size of the procedure as small as possible by eliminating unneeded code. Ask yourself if that IF statement will ever run all of its branches -- if not remove them. Better yet -- create other stored procedures that handles the function of each IF branch. Also see if there are segments of code that you use over and over again which can be extracted and made into separate stored procedures. Finally, understand the uses of the CASE statement. CASE statements can sometimes eliminate large amounts of code if you know how to use them properly.
Use the new ANSI JOIN syntax instead of the old style joins. The new join syntax has a slight performance advantage over the old way of using the WHERE clause for a join. The new syntax also tends to have better readability and should become the norm in your Transact-SQL coding.
Some schools of thought will tell you to replace dynamic portions of your code with parameterized queries. This switch depends on your situation as I have found that in some cases, the dynamic query performs better even though the cached plan is not always used. This is up to your own research based on the query and your database.
Look for objects that are not called with qualified owner names. Each time the query is run without qualified owner names on the objects referenced within
Recompiling Queries
Even if you have optimized queries by looking at the Execution Plan and the code, you may still have a problem that the vast majority of developers do not even consider. This problem is the performance cost taken every time a query has to create a new plan or recompile. Recompiling queries are usually the easiest to fix and can make a dramatic improvement on the performance of many applications. You should keep in mind as you look at the list of recompiling stored procedures that there are legitimate reasons that a stored procedure recompiles. It is just the ones that seem to recompile each time they are executed that you should worry about in the short term. You can look at the others later and determine if they are recompiling for legitimate reasons or not. Look for a mixture of DML and DDL statements. Do not mix the creation of objects and use of those objects in your code. Move all object creation to the top of your query and you should be able to avoid this problem.
Look for ANSI SET commands. Changing the status of SET ANSI_DEFAULTS, SET ANSI_NULLS, SET ANSI_PADDING, SET ANSI_WARNINGS, and SET CONCAT_NULL_YIELDS_NULL will cause the query to recompile each time it is executed. Make sure you really need to change these settings before you do so inside of a query.
Conclusion
We have looked at the Execution Plan, analyzed the code, and look for recompiles; now what? Just because everything looks fine, doesn't mean that the query will run satisfactorily in every single scenario. Come up with all the different test cases you can think of for the query. How does it run against different sizes of data sets? How does it run with different sets of parameters? What happens if you run the query multiple times using multiple Query Analyzer connections? Whatever you can think of in your particular case, needs to be traced and analyzed. Don't just run the query once and say "I tuned this query and it is ready." Do the hardest thing in the world and convince your clients and managers that you need time to thoroughly test a new query or recently fixed query.
Reference
http://msdn.microsoft.com