views:

50

answers:

5

I'm in a situation where I have to improve the performance of about 75 stored procedures (created by someone else) used for reporting. The first part of my solution was creating about 6 denormalized tables that will be used for the bulk of the reporting. Now that I've created the tables I have the somewhat daunting task of determining what Indexes I should create to best improve the performance of these stored procs.

I'm curious to see if anyone has any suggestions for finding what columns would make sense to include in the indexes? I've contemplated using Profiler/DTA, or possibly fasioning some sort of query like the one below to figure out the popular columns.

SELECT name, Count(so.name) as hits, so.xtype
from syscomments as sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE   sc.text like '%ColumnNamme%'
AND xtype = 'P'
Group by name,so.xtype
ORDER BY hits desc

Let me know if you have any ideas that would help me not have to dig through these 75 procs by hand.

Also, inserts are only performed on this DB once per day so insert performance is not a huge concern for me.

+1  A: 

You can use SQL Server profiler in SSMS to see what and how your tables are being called then using the Database Tuning Tool in profiler to at least start you down the correct path. I know most DBA's will probably scream at me for recommending this but for us non-DBA types such as myself it at least gives us a starting point.

bechbd
Yeah that's one of the options I'm considering. I've heard from a lot of people that you shouldn't rely on this method to generate your indexes though.
Abe Miessler
I've done a fair amount of tuning and this is an approach I've used with great success. From the profiler you can get all kinds of useful information especially CPU and Disc IO usages. That will show you which SP's are the slowest (or at least the ones that may benefit most from tuning). You can then break those open and look at the query plan - although does anyone really understand a Sql Query Plan?
MrTelly
It sounds like most people think it's a good idea to use profiler/dta to get an idea of what indexes I need. What kind of problems can I expect from running the profiler on my production server for several hours?
Abe Miessler
Be careful about the priority of traces on your live system. If too high, they will interfere with the performance of the live site. I believe that if you run a trace from the profiler UI, it automatically runs with a high priority so I'd recommend not using the UI to run traces on a live system (the command line version is ok though).
adrianbanks
+2  A: 

If you know all of the activity is coming from the 75 stored procedures then I would use profiler to track which stored procedures take the longest and are called the most. Once you know which ones are then look at those procs and see what columns are being used most often in the Where clause and JOIN ON sections. Most likely, those are the columns you will want to put non-clustered indexes on. If a set of columns are often times used together then there is a good chance you will want to make 1 non-clustered index for the group. You can have many non-clustered indexes on a table (250) but you probably don't want to put more than a handful on it. I think you will find the data is being searched and joined on the same columns over and over. Remember the 80/20 rule. You will probably get 80% of your speed increases in the first 20% of the work you do. There will be a point where you get very little speed increase for the added indexes, that is when you want to stop.

RandomBen
+2  A: 

Any suggestions for identifying what indexes need to be created?

Yes! Ask Sql Server to tell you.

Sql Server automatically keeps statistics for what indexes it can use to improve performance. This is already going on in the background for you. See this link:
http://msdn.microsoft.com/en-us/library/ms345417.aspx

Try running a query like this (taken right from msdn):

SELECT mig.*, statement AS table_name,
    column_id, column_name, column_usage
FROM sys.dm_db_missing_index_details AS mid
CROSS APPLY sys.dm_db_missing_index_columns (mid.index_handle)
INNER JOIN sys.dm_db_missing_index_groups AS mig ON mig.index_handle = mid.index_handle
ORDER BY mig.index_group_handle, mig.index_handle, column_id;

Of course, to make real, accurate use of this information you will need to profile actual execution times of your key procedures both before and after any changes.

Joel Coehoorn
+2  A: 

I concur with bechbd - use a good sample of your database traffic (by running a server trace on a production system during real office hours, to get the best snapshot), and let the Database Tuning Advisor analyze that sampling.

I agree with you - don't blindly rely on everything the Database Tuning Advisor tells you to do - it's just a recommendation, but the DTA can't take everything into account. Sure - by adding indices you can speed up querying - but you'll slow down inserts and updates at the same time.

Also - to really find out if something helps, you need to implement it, measure again, and compare - that's really the only reliable way. There are just too many variables and unknowns involved.

And of course, you can use the DTA to fine-tune a single query to perform outrageously well - but that might neglect the fact that this query is only ever called one per week, or that by tuning this one query and adding an index, you hurt other queries.

Index tuning is always a balance, a tradeoff, and a trial-and-error kind of game - it's not an exact science with a formula and a recipe book to strictly determine what you need.

marc_s
A: 

If this is strictly a reporting database and you need performance, consider moving to a data warehouse design. A star or snowflake schema will outperform even a denormalized relational design when it comes to reporting.

Jeff Hornby