DBCC IndexDefrag

Being day 16 of the DBCC Command month at SteveStedman.com, today’s featured DBCC Command is DBCC INDEXDEFRAG.

Description:

DBCC INDEXDEFRAG was used for to defragment indexes on SQL Server 2000, the same thing can be done with Alter Index on newer versions of SQL Server..

DBCC INDEXDEFRAG Syntax:

dbcc indexdefrag
(
    { 'database_name' | database_id | 0 }
    , { 'table_name' | table_id | 'view_name' | view_id }
    [ , { 'index_name' | index_id }
    [ , { partition_number | 0 } ] ]
)
    [ WITH NO_INFOMSGS ]

For more info on index defragmentation, check out the Database Health Reports application. Below is a sample screenshot of the Index Fragmentation report.

Index_Fragmentation_Report

Notes:

Note that DBCC INDEXDEFRAG was deprecated and replaced by ALTER INDEX.

For more information see TSQL Wiki DBCC indexdefrag.

DBCC Command month at SteveStedman.com is almost as much fun as conveyor belt sushi.

DBCC FreeProcCache

Being day 12 of the DBCC Command month at SteveStedman.com, today’s featured DBCC Command is DBCC FREEPROCCACHE.

Description:

DBCC FREEPROCCACHE is used for purge all of the parsed query plans out of memory. This is commonly used in development environments, but not as common in a production environment.

Use in a development environment is common, for instance when you are working on performance tuning, or parameterization of queries. You can clear the procedure cache with DBCC FreeProcCache, run the program or web page that may be using the database, then see what is in the procedure cache. This can be useful in finding queries that may need to be parameterized. Another way to use would be to find out what queries are being run by some program. To do this you would start by working with a database that is not being used by others, clearing the procedure cache with DBCC FreeProcCache, then run the program you are trying to figure out, then look at what is in the cache, again this is something that could be done in a development or test environment, but I wouldn’t recommend doing it in production.

Use in a production environment should be rare, this is one of the common things to try when SQL Server is having difficulty. If you are are the point that SQL Server is extremely slow to respond and you have been unable to find the cause, one thing to try is to free the procedure cache with DBCC FreeProcCache and see if that fixes the problem.

DBCC FreeProcCache Syntax:

dbcc freeproccache
[ ( @HANDLE | 'POOL NAME' ) ]
[ WITH NO_INFOMSGS ]

Example:

The following example is from a development envioronment using the AdventureWorks2012 Database.

First we connect to AdventureWorks2012 and see what is in the cache.

USE AdventureWorks2012;
GO

SELECT size_in_bytes, text
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st;

DBCC_FreeProcCache1
Here we see that there is plenty in the cache. Next we cleare the cache with DBCC FreeProcCache and take another look at what is in the cache.

DBCC FREEPROCCACHE;

SELECT size_in_bytes, text
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st;

After running DBCC FreeProcCache you can see that there is nothing left in the cache.
DBCC_FreeProcCache2When the very next query is run, it will need to be reparsed rather than using an already parsed query in the cache.  This will take a bit longer than if there was already a parsed plan to run.  Lets run 3 queries, then take a look at the cache.

GO
SELECT FirstName, MiddleName, LastName
 FROM person.Person p
 WHERE FirstName like 'John';

GO
SELECT FirstName, MiddleName, LastName
 FROM person.Person p
 WHERE FirstName like 'Mary';
GO
SELECT FirstName, MiddleName, LastName
 FROM person.Person p
 WHERE FirstName like 'Bill';

Notice the GO Statement between each query. This tells SSMS to run each query as a separate batch. Without the GO statement the 3 queries would have been parsed as a single batch.
DBCC_FreeProcCache3
Here we see the results from the three queries. The first two returned results, and the third one had no rows in the result set. Now lets take a look at the cache

SELECT size_in_bytes, text
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st;

Below we see a total of 20 items in the cache now. the top item highlighted in blue is the query we used to see what was in the cache, the second block highlighted in red contains the 3 queries from above, and the third rest of them are queries being run by SQL or other supporting queries.  For instance line 13 is the dm_exec_sql_text which is called from the query above that checks the plan.DBCC_FreeProcCache4

If we wanted to filter this down to just the queries we had written you could do it by adding a WHERE text LIKE … clause to the query as shown here.

SELECT size_in_bytes, text
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE text LIKE N'SELECT FirstName%';

Here we see that only the three queries show up, and that each of those three takes up about 40K of memory on SQL Server. DBCC_FreeProcCache5So why are there three copies of the same SELECT statement, this seems a bit wasteful. Indeed it does, for more information see an earlier post called How much Procedure Cache memory does one SQL Statement take up? There are ways to correct this.

Using DBCC FreeProcCache For A Specific Plan Handle

If you wanted to clear just a single plan handle, and not all the plan handles, you could use the optional parameter called @handle.

To get the plan handle, we start by modifying our earlier query to show us what is in the plan cache. You could leave out the WHERE clause on your own system, but I have it here to show us just the three queries in question from above.


SELECT size_in_bytes, text, plan_handle
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE text LIKE N'SELECT FirstName%';

DBCC_FreeProcCache7

Here we see the same three query plans from earlier, with an addition column called plan_handle. To free a single plan handle, we would just copy the numeric plan handle, and add that into the DBCC FreeProcCache query.


DBCC FREEPROCCACHE(0x060007000100FF3310B8DA7D0600000001000000000000000000000000000000000000000000000000000000);

SELECT size_in_bytes, text, plan_handle
 FROM sys.dm_exec_cached_plans
 CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
WHERE text LIKE N'SELECT FirstName%';

DBCC_FreeProcCache8

Where we only see 2 of the three original queries in the plan cache.

How big is my Procedure Cache?

You can run the following query to check the size of your procedure cache.


SELECT count(*) AS NumPlans, objtype as Type,
SUM(size_in_bytes)/(1024.0*1024.0) AS size_in_mb
FROM sys.dm_exec_cached_plans
GROUP BY objtype;

Which produces the following results on my test server.

DBCC_FreeProcCache9

Database Health Reports and the Plan Cache

You can also view the plan cache using the Database Health Reports application as shown here.

DBCC_FreeProcCache10

Notes:

For more information see TSQL Wiki DBCC freeproccache.

DBCC Command month at SteveStedman.com is almost as much fun as eating jello.

DBCC DBReIndex

Being day nine of the DBCC Command month at SteveStedman.com, today’s featured DBCC Command is DBCC DBREINDEX.

Microsoft recommends avoiding the use of DBCC DBREINDEX.

DBCC DBReIndex has been deprecated  meaning that Microsoft has announced that DBCC DBReIndex will be going away in future versions of SQL Server

Over time as you insert, update and delete from tables various clustered and non-clustered indexes will end up getting fragmented. Fragmented means that the contents of the index is scattered over more pages than it could be, and that the pages holding the index are partially full.  DBCC ReIndex (or the alternative offered below) reorganizes the index data in those pages so that there is less waste, less fragmentation, and all of the index data is packed into the data pages tighter. Over time the index may become fragmented again.

DBCC DBREINDEX Syntax:

dbcc dbreindex
(
    'table_name'
    [ , 'index_name' [ , fillfactor ] ]
)
    [ WITH NO_INFOMSGS ]

Alternative to DBCC DBReIndex

There is more functionality in the ALTER INDEX than in DBCC DBReIndex.

The following example shows how to use ALTER INDEX insted of DBCC DbReIndex.

</pre>
ALTER INDEX [ClusteredCPU]
 ON [dbo].[CPU]
 REORGANIZE WITH ( LOB_COMPACTION = ON );
<pre>

Detecting Fragmented Indexes

The Index Fragmentation Report in the Database Health Reports project can be used to find fragmented indexes as shown here.

Index_Fragmentation_Report

Additionally with the Database Health Reports project, the Fragmented Indexes Advisor can help you de-fragment those indexes, rather than using the obsolete DBCC DBReIndex as shown here

Fragmented_Index_Advisor

Notes:

Use ALTER INDEX instead of DBCC DBReIndex.

For more information see TSQL Wiki DBCC dbreindex.

DBCC Command month at SteveStedman.com is almost as much fun as creating a quilt.

Working on the next beta of the Database Health Reports… Any requests?

I am currently working on the next beta of the Database Health Reports.  I you haven’t seen the program check it out at http://DatabaseHealth.SteveStedman.com.

I am looking for idea of new features to add in the next beta, and I just want to ask…. Any Suggestions?

 

Do you have any suggestions for another report or feature to add to the Database Health Reports?  Maybe something that you check on every day that you would like to see included in the database health reports?  Just post your request as a response to this blog entry.

 

If you want to Download the Database Health Reports to take a look before making a suggestion, just click here.

 

Database Health Reports program is a powerful performance monitoring and diagnostics solution that alerts administrators to health, performance or availability problems within their SQL Server environment, all from a central console.

The Database Health Reports project is provide free of charge by Steve Stedman to the SQL Server community.

 

Thanks,

-Steve Stedman

Index Overview – Clustered and Nonclustered

This is intended as a brief overview of indexing on SQL Server. Understanding and using indexes can lead to some major performance improvements.

Non-Clustered Indexes

Non-Clustered indexes are often times considered traditional indexing – contains pointers to the data. This is similar to the index at the back of a book. If you open a book to the index, then look up a term you are given the page numbers that the term is on. A non-clustered index is similar to this process, the non-clustered index contains a list of data, then finally it has a link to the actual location for that data similar to the page number in the back of a book.
The Non-Clustered index contain only the data specified in the index, and the primary key information to get to the rest of the data. Non-Clustered indexes do not change the base layout of the tables, they are a copy of the data, and use pointers to get to the data.
Non-Clustered indexes can be created on most data types including char(), varchar(), and uniqueidentifiers. Non-Clustered indexes can improve performance by adding multiple columns.

Clustered Indexes

A clustered index is an index that reorganizes the actual data on disk, causing the entire base table structure to change. Since the clustered index rearranges the base table, only one clustered index is allowed per table.
The term clustering refers to the act of adding a clustered index. Clustering can significantly increase the size of a table and the database if it is not used correctly.
When used correctly clustered indexes can dramatically increase performance.

Covered Indexes

A covered index, is not another type of index, it usually applies to a non-clustered index and the index is considered covering when the index contains everything that a query is looking for without accessing the base table.
Covered indexes can lead to major performance increases since the base table doesn’t need to be accessed.

Index Usage Terminology

Scan: An Index Scan accesses all the rows in the index.
Seek: An Index Seek uses selective rows in the index.

The Seek is much quicker than the scan.
The index scan is usually much quicker than a full table scan.

Additional Index Resources

Installing Sample Databases for SQL Server 2008R2

As I work on testing the Database Health Reports project, I have configured several test servers running as virtual machines using Hyper-V. Part of setting these up for testing, I usually end up installing the sample databases for SQL Server. The sample databases give me something to test against, and what usually ends up happening is I end up polluting the sample database over time with lots of test tables, bad indexes, and all the stuff that you should keep in a test database, and never actually put in a production system. Occasionally I need to wipe the server clean and start over, so when I do this I usually end up re-installing the sample databases. I do this just often enough to forget exactly where to get the sample databases from. To solve that problem I have created this blog posting so that I have somewhere to look next time I need the sample databases.

Step 1. Download the sample files from Codeplex.

There are a couple different versions of sample files available. I usually use the AdventureWorks 2008 OLTP Script. The OLTP (OnLine Transaction Processing) sample doesn’t include the data warehouse samples, and it is just quick and easy to use.
Download from here:
http://msftdbprodsamples.codeplex.com/releases/view/89502
AdventureWorks is the name of the sample database, which replaces the old Pubs database from earlier versions of SQL Server, and the NorthWind sample database from SQL Server 2005.
Download the a zip file containing the scripts needed to install AdventureWorks. The filename should be AdventureWorks 2008 OLTP Script.zip.

Step 2: Run the scripts.

To run the scripts either unzip the file and save the contents somewhere.
AdventureWorks1

Then browse into the AdventureWorks 2008 OLTP Script directory.

AdventureWorks2

Open the instawdb.sql script with SQL Server Management Studio.

AdventureWorks3

You will want to enable Full Text Search before running the script.

SQLCMD mode will need to be enabled to run the script. If the script is run without SQL Command mode, the following errors will be generated. To Enable SQLCMD mode, choose the SQLCMD Mode option from the query menu in SSMS.
AdventureWorks4
If the script is run without setting up the directories correctly the following error will be displayed.

AdventureWorks5
A fatal scripting error occurred.
Variable SqlSamplesSourceDataPath is not defined.

To fix the error, just set up the directories edit the 2 lines at about lines 36 and 37, first uncomment them, then change the directories to match the directory of your SQL Server, and the directory that the samples were downloaded to as shown in the following directory.

AdventureWorks7 Once the directories have been edited, then just run the script. The script may run for a few minutes depending on your server speed. If the script runs successfully it will generate the following output.

AdventureWorks8

Then refresh the database tree in the object explorer and the AdventureWorks2008 database will show up. Go ahead and browse the tables and take a look around.

AdventureWorks9

Not exactly a straightforward process, but if you follow the steps you will get The AdventureWorks 2008 database running on SQL Server 2008R2.
Enjoy