Thursday, October 13, 2011

Ever wondered which tables in your databases are being used most heavily? Below is a script for SQL Server 2005/2008 that will tell you exactly that - which tables are utilized most and what percentage of that use is reads and what percentage is writes. Heavily utilized tables are prime candidates for SQL Server's Table Partitioning or moving to another filegroup (not necessarily recommended with EnterpriseOne) and besides, it's just gosh-darn fun knowing what's going on inside your databases.

Big Caveat - This script makes use of the sys.dm_db_index_usage_stats SQL Dynamic Management View. The values returned by this DMV do not persist beyond server restarts. This means the information it gathers is only valid since the last SQL Server restart or (less likely) database attach. So, if you just re-started your database server you are not going to get good numbers. Also, this information is kept in cache and is subject to memory pressure flushing, not a likely scenario but possible.

The script will gather index information from which one can infer table access information. It uses the sp_MSForEachDB stored procedure to run through all databases on the instance, places the information in a temporary table, sums the values for index reads and writes, does a bunch of fancy math, rolls it up to the table level and returns the results to show reads, writes, percent of each and the type of index read.

From this we can determine what tables are being utilized heavily and in what manner. The last four columns deal with methods of index read access and are a bit beyond the scope of this article but if you really want to discuss that just ask in the comments and I'll be glad to expand.

You cannot use this for non-SQL Server databases, even with slight modifications. The basis for the script is the sys.dm_db_index_usage_stats Dynamic Management View, which is particular to SQL Server.

We use the sum of UserSeeks and UserScans because user_lookups only returns results for clustered indexes only. Seeks on non-clustered indexes reference the base row and this seek is what shows up in user_lookups.

User_lookups is not included in totals since some of the lookups included in it are already included in UserSeeks.

Index Scans touch every row in a table while Index Seeks only hits rows that qualify. The query optimizer tries to find an index that it can utilize and if it does the result will be an index seek. If it cannot find a suitable index the result will be an index scan.

The scan will simply walk through the leaf pages and, as a result, is not very efficient. The seek will utilize the the B-tree structure in a more efficient path to the leaf page containing the data.

You can indeed use these figures to analyze index performance. If you are seeing a highly utilized table with the majority of accesses being scans it may be time to add an index or two.

thanks, great info, here's another piece of code that i like to use in order to find a list of the most populated tables within my database : http://www.sqlpentruincepatori.ro/most-populated-tables-from-the-database-sql-server/

hii use this select but i have a problem.how can i save this information before server reset or is shutdown.because information in sys.dm_db_index_usage_stats be deleted in server rest.please help me.thank you