Index Fill Factor in SQL Server

Today once again I felt to write something about Index, soopen up the listof Index articles I have written, find out the topic which are stillmissing for concept of Index and thought to write about fill factor.
Generally, when you create an Index, your data get stored inB-Tree format where you can find “Root Page”, may be “Intermediate Page” and “LEAFPage”. “Leaf Page” would have your actual data sorted in order of Index key andeach “Leaf Page” would be of 8KB.
When you insert/update/delete data to/from table, it triesto insert in the proper data page according to the record you are inserting.For example, you have Index on SSN number you are inserting new row with SSN number,SQL Server tries to insert that record in the appropriate page, suppose yourSSN starts with “2” so it will find what is the last page which has SSN numberstarts with “2”, SQL Server will insert your new row in that page only. If your8 KB page is full and don’t have room to accommodate new row whose SSN startswith “2”, it will split page and the data in that page will be shared betweentwo pages so now you have two pages which are half full so your row will be accommodatedin that page.
If your page would already had space for accommodating newrow, you wouldn’t need to wait for extra I/O overhead and wait until page splitgets finish and space for your row would become available.
This is the time when FillFactor comes into the picture.Fill Factor decides how much your page would be filled up initially. Supposeyou give 10 in FillFactor than your data page will consume only 10% of your 8KBpage size and when you exceed this limit of 10%, it keeps 90% page empty andcreate new page for other records.  Now,when you insert new records, you don’t need to worry about I/O overhead of pagesplit as you would have 90% free space and your record will be accommodate inthat space easily. So, if you have lower number of Fillfactor, you can decreaseI/O over head generated by Page Split which helps you to write your datafaster.
Now, you might be thinking now that why shouldn’t I use lownumber always like 5% or 10% in Fillfactor? Well, it will decrease your pagesplit but it will increase number of data page in your index so every time youscan your index, you have to read more pages and it is again over head whilereading the data and decrease the speed of reading data. Suppose you have 10records in one table and its size is 8KB, you can fit all 10 records in onepage only but if you have fill factor of 50 than those 10 records will bestored in two pages rather than one while creating an index.
Uff, what to do now? if we decrease fillfactor figure, ithelps in writing but creates problem in reading and if we increase fillfactorfigure may be 100% than helps in reading but creates issues while writing indatabase?
You have to be reasonable and have to take decision basedthe load on your database, you have to decide first that you have more writesor more read?
Personally I majority go for figure somewhere between 80 to90 for fillfactor so that you have some space remain for new records anddecrease page split at the same time, we don’t keep too much free space in datapages so number of pages doesn’t get increased. Even, it is not final figure I use for all my databases, if my database is read only or very rare insert/update, I would go even for 100% Fillfactor and if my database is write intensive, I would have even 50% Fillfactor.
BTW, you can define Fill Factor while creating an Indexor rebuildingan Index or you can set default value for fill factor via following T-SQL (bydefault it is 0 in SQL Server).
–turning onadvanced configuration option
Sp_configure ‘show advanced options’,1
GO
RECONFIGURE
GO
–setting upfill factor
sp_configure ‘fill factor’, 90
GO
RECONFIGURE
GO
Reference: Ritesh Shah

http://www.sqlhub.com
Note: Microsoft Books online is a default reference of all articles butexamples and explanations prepared by Ritesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Index Fill Factor in SQL Server

Today once again I felt to write something about Index, soopen up the listof Index articles I have written, find out the topic which are stillmissing for concept of Index and thought to write about fill factor.
Generally, when you create an Index, your data get stored inB-Tree format where you can find “Root Page”, may be “Intermediate Page” and “LEAFPage”. “Leaf Page” would have your actual data sorted in order of Index key andeach “Leaf Page” would be of 8KB.
When you insert/update/delete data to/from table, it triesto insert in the proper data page according to the record you are inserting.For example, you have Index on SSN number you are inserting new row with SSN number,SQL Server tries to insert that record in the appropriate page, suppose yourSSN starts with “2” so it will find what is the last page which has SSN numberstarts with “2”, SQL Server will insert your new row in that page only. If your8 KB page is full and don’t have room to accommodate new row whose SSN startswith “2”, it will split page and the data in that page will be shared betweentwo pages so now you have two pages which are half full so your row will be accommodatedin that page.
If your page would already had space for accommodating newrow, you wouldn’t need to wait for extra I/O overhead and wait until page splitgets finish and space for your row would become available.
This is the time when FillFactor comes into the picture.Fill Factor decides how much your page would be filled up initially. Supposeyou give 10 in FillFactor than your data page will consume only 10% of your 8KBpage size and when you exceed this limit of 10%, it keeps 90% page empty andcreate new page for other records.  Now,when you insert new records, you don’t need to worry about I/O overhead of pagesplit as you would have 90% free space and your record will be accommodate inthat space easily. So, if you have lower number of Fillfactor, you can decreaseI/O over head generated by Page Split which helps you to write your datafaster.
Now, you might be thinking now that why shouldn’t I use lownumber always like 5% or 10% in Fillfactor? Well, it will decrease your pagesplit but it will increase number of data page in your index so every time youscan your index, you have to read more pages and it is again over head whilereading the data and decrease the speed of reading data. Suppose you have 10records in one table and its size is 8KB, you can fit all 10 records in onepage only but if you have fill factor of 50 than those 10 records will bestored in two pages rather than one while creating an index.
Uff, what to do now? if we decrease fillfactor figure, ithelps in writing but creates problem in reading and if we increase fillfactorfigure may be 100% than helps in reading but creates issues while writing indatabase?
You have to be reasonable and have to take decision basedthe load on your database, you have to decide first that you have more writesor more read?
Personally I majority go for figure somewhere between 80 to90 for fillfactor so that you have some space remain for new records anddecrease page split at the same time, we don’t keep too much free space in datapages so number of pages doesn’t get increased. Even, it is not final figure I use for all my databases, if my database is read only or very rare insert/update, I would go even for 100% Fillfactor and if my database is write intensive, I would have even 50% Fillfactor.
BTW, you can define Fill Factor while creating an Indexor rebuildingan Index or you can set default value for fill factor via following T-SQL (bydefault it is 0 in SQL Server).
–turning onadvanced configuration option
Sp_configure ‘show advanced options’,1
GO
RECONFIGURE
GO
–setting upfill factor
sp_configure ‘fill factor’, 90
GO
RECONFIGURE
GO
Reference: Ritesh Shah

http://www.sqlhub.com
Note: Microsoft Books online is a default reference of all articles butexamples and explanations prepared by Ritesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Understand SET STATISTICS IO as a first step for performance tuning in SQL Server

SET STATISTICS IO”provides us very crucial information about the query we run, like scan count,logical read, physical read etc. but this command is really very ignored. Whileit’s coming to query optimization, many newbie or less experience person usedto talk about DTA, profiler etc. but they JUST IGNORE simple yet powerfulcommand “SET STATISTICS IO” whereasthey first need to look at the information provided by “SET STATISTICS IO” so that you can move ahead and dig more detailswith the information provided by “SETSTATISTICS IO”.
Let us see how it practically useful for us.
We are going to create one database, named “SQLHub” and onetable, named “Orders” under “SQLHub” database. “Orders” table would have approx1,00,000 rows dynamically inserted.
–create onedatabase which you can delete after running this example
create database SQLHub
GO
USE SQLHub
GO
–if orderstable is already there. you can delete it than create new one with name”Orders”
IF OBJECT_ID(‘orders’, ‘U’) IS NOT NULL BEGIN
      DROP TABLE orders
END
GO
–creating table
CREATE TABLE orders (OrderID INT IDENTITY, OrderDate DATETIME, Amount MONEY, Refno INT)
GO
–inserting100000 fack rows into table (BTW, thank to Jacob Sebastian, copy in INSERTscript from one of his demo to generate big table)
INSERT INTO orders (OrderDate, Amount, Refno)
SELECT TOP 100000
      DATEADD(minute, ABS(a.object_id % 50000 ), CAST(‘2010-02-01’ AS DATETIME)),
      ABS(a.object_id % 10),
      CAST(ABS(a.object_id) AS VARCHAR)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
GO
Now we are ready to see how query works. Let us create onesimple “SELECT” T-SQL query with “SET STATICTICS IO”.
SET STATISTICS IO ON
–you might havedifferent refno in your table, so please check it first
SELECT * from orders where refno=23
SET STATISTICS IO OFF
–here is thestats info came via “SET STATISTICS ON” in “Message” tab.
–(1982 row(s)affected)
–Table’orders’. Scan count 1, logical reads 409, physical reads 0, read-ahead reads0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
After running this query, you would get its results inresult tab and some stats in “Message” tab, look at the screen capture.

You can see “Logical Read 409”. To find out all rows which hasrefno 23, SQL Server has to go for 409 pages internally. Now let us create anIndex on RefNo column and see stats.
–creatingclustered index, however it is not meeting the criteria I have
–given inarticle, but this is ok for example
CREATE CLUSTERED INDEXidx_refno ON orders(refno)
GO
After creating “Clustered Index” on “Orders” table for “refno”column, let us see the same query.
SET STATISTICS IO ON
SELECT * from orders where refno=23
SET STATISTICS IO OFF
–here is thestats info came via “SET STATISTICS ON” in “Message” tab.
–(1982 row(s)affected)
–Table’orders’. Scan count 1, logical reads 14, physical reads 0, read-ahead reads 0,lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
GO

Seescreen capture of this query:

 

You can see now “Logical Read 14” rather than “409”, you seehow much difference clustered index have made? And you don’t need to go toprofiler to see this difference, even no need for execution plan in this case. HoweverI am not against the use of profiler and execution plan. They both are veryintelligent and useful tools but just wanted to clear it up that; we can getimportant information from simple command like “SET STATISTICS IO” too.
Apart from “Logical Read”, it provides you many moreinformation in “Message” tab which you can see above like “Scan Count”, “PhysicalRead”, “Read-Ahead reads”, “log logical reads”, “lob physical reads” etc. youcan get description of all these from Microsoft’s MSDN.
If you want to refer all other articles related to index, clickhere.
Reference: Ritesh Shah

http://www.sqlhub.com
Note: Microsoft Books online is adefault reference of all articles but examples and explanations prepared byRitesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Understand SET STATISTICS IO as a first step for performance tuning in SQL Server

SET STATISTICS IO”provides us very crucial information about the query we run, like scan count,logical read, physical read etc. but this command is really very ignored. Whileit’s coming to query optimization, many newbie or less experience person usedto talk about DTA, profiler etc. but they JUST IGNORE simple yet powerfulcommand “SET STATISTICS IO” whereasthey first need to look at the information provided by “SET STATISTICS IO” so that you can move ahead and dig more detailswith the information provided by “SETSTATISTICS IO”.
Let us see how it practically useful for us.
We are going to create one database, named “SQLHub” and onetable, named “Orders” under “SQLHub” database. “Orders” table would have approx1,00,000 rows dynamically inserted.
–create onedatabase which you can delete after running this example
create database SQLHub
GO
USE SQLHub
GO
–if orderstable is already there. you can delete it than create new one with name”Orders”
IF OBJECT_ID(‘orders’, ‘U’) IS NOT NULL BEGIN
      DROP TABLE orders
END
GO
–creating table
CREATE TABLE orders (OrderID INT IDENTITY, OrderDate DATETIME, Amount MONEY, Refno INT)
GO
–inserting100000 fack rows into table (BTW, thank to Jacob Sebastian, copy in INSERTscript from one of his demo to generate big table)
INSERT INTO orders (OrderDate, Amount, Refno)
SELECT TOP 100000
      DATEADD(minute, ABS(a.object_id % 50000 ), CAST(‘2010-02-01’ AS DATETIME)),
      ABS(a.object_id % 10),
      CAST(ABS(a.object_id) AS VARCHAR)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
GO
Now we are ready to see how query works. Let us create onesimple “SELECT” T-SQL query with “SET STATICTICS IO”.
SET STATISTICS IO ON
–you might havedifferent refno in your table, so please check it first
SELECT * from orders where refno=23
SET STATISTICS IO OFF
–here is thestats info came via “SET STATISTICS ON” in “Message” tab.
–(1982 row(s)affected)
–Table’orders’. Scan count 1, logical reads 409, physical reads 0, read-ahead reads0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
After running this query, you would get its results inresult tab and some stats in “Message” tab, look at the screen capture.

You can see “Logical Read 409”. To find out all rows which hasrefno 23, SQL Server has to go for 409 pages internally. Now let us create anIndex on RefNo column and see stats.
–creatingclustered index, however it is not meeting the criteria I have
–given inarticle, but this is ok for example
CREATE CLUSTERED INDEXidx_refno ON orders(refno)
GO
After creating “Clustered Index” on “Orders” table for “refno”column, let us see the same query.
SET STATISTICS IO ON
SELECT * from orders where refno=23
SET STATISTICS IO OFF
–here is thestats info came via “SET STATISTICS ON” in “Message” tab.
–(1982 row(s)affected)
–Table’orders’. Scan count 1, logical reads 14, physical reads 0, read-ahead reads 0,lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
GO

Seescreen capture of this query:

 

You can see now “Logical Read 14” rather than “409”, you seehow much difference clustered index have made? And you don’t need to go toprofiler to see this difference, even no need for execution plan in this case. HoweverI am not against the use of profiler and execution plan. They both are veryintelligent and useful tools but just wanted to clear it up that; we can getimportant information from simple command like “SET STATISTICS IO” too.
Apart from “Logical Read”, it provides you many moreinformation in “Message” tab which you can see above like “Scan Count”, “PhysicalRead”, “Read-Ahead reads”, “log logical reads”, “lob physical reads” etc. youcan get description of all these from Microsoft’s MSDN.
If you want to refer all other articles related to index, clickhere.
Reference: Ritesh Shah

http://www.sqlhub.com
Note: Microsoft Books online is adefault reference of all articles but examples and explanations prepared byRitesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Find missing Index with DMVs in SQL Server 2005/2008/Denali

In the previous articles I saw how to find unused index sothat you can find it and drop it to improve performance of your Insert /Update/Delete statement and claim some disk space which is really useful inproduction server.
Today I will be exploring the script to find the missingindex, after finding that index; you can decide whether to create it or notbased on the requirement of your application. 
There are many important DMVs (Dynamic Management View)there in SQL Server 2005 and higher version which are keeping information youneed to know to find missing index. Following is the list of those DMVs.
sys.dm_db_missing_index_details”:  This DMV returns details about missing indexyou need to create. For more information on this, please click here.
sys.dm_db_missing_index_group_stats”: This DMV returns thesummary of benefit you would have received if you would have the particular index.For more information on this, please click here.
sys.dm_db_missing_index_groups”: This DMV returnsinformation about what missing index are contained in what missing index grouphandle. For more information on this, please click here.
sys.dm_db_missing_index_columns(Index_Handle)”:  This DMV gives you an idea about what columnsare missing in Index, it is based on the “Index_Handle” field of “Sys.dm_db_missing_index_details”DMV. For more information on this, please clickhere.
Let us run all these four DMVs to see what it has for us:
select * from sys.dm_db_missing_index_details
select * from sys.dm_db_missing_index_group_stats
select * from sys.dm_db_missing_index_groups
–43816 is oneof the I have copided from my “Index_Handle” column of
–sys.dm_db_missing_index_detailsDMV, you might get something else than 43816
select * from sys.dm_db_missing_index_columns(43816)
So these are the DMVs which will be useful in order to find missingindex, we are going to use first three of the above DMVs to find our missingindex.
Here you go!!!!
SELECT
      avg_total_user_cost *avg_user_impact * (user_seeks +user_scans) ASPossibleImprovement
      ,last_user_seek
      ,last_user_scan
      ,statementAS Object
      ,‘CREATEINDEX [IDX_’ + CONVERT(VARCHAR,GS.Group_Handle) + ‘_’ + CONVERT(VARCHAR,D.Index_Handle) + ‘_’
      + REPLACE(REPLACE(REPLACE([statement],‘]’,),‘[‘,),‘.’,) + ‘]’
      +‘ ON ‘
      + [statement]
      + ‘ (‘+ ISNULL (equality_columns,)
    + CASE WHENequality_columns IS NOTNULL ANDinequality_columns IS NOTNULL THEN ‘,’ ELSE END
    + ISNULL (inequality_columns, )
    + ‘)’
    + ISNULL (‘ INCLUDE (‘ + included_columns + ‘)’, )
      AS Create_Index_Syntax
FROM
      sys.dm_db_missing_index_groups ASG
INNER JOIN
      sys.dm_db_missing_index_group_stats AS GS
ON
      GS.group_handle = G.index_group_handle
INNER JOIN
      sys.dm_db_missing_index_details ASD
ON
      G.index_handle = D.index_handle
Order By PossibleImprovement DESC
This is just a basic advice from DMVs regarding what indexesare missing and you have to create it, finally it’s up to you based on your requirementwhether to create index or not. You have to see the table name and columnwhether it has any selectivity or not then decide whether to create that or notas more index on table might improve performance of your SELECT but it willharm other DML statements so it is always advisable to use your human skills todecide rather than leave everything on DMVs.  
These DMVs could keep information for maximum of 500indexes.
Enjoy Indexing!!!!
If you want to refer all other articles related to index, clickhere.
Reference: Ritesh Shah
http://www.sqlhub.com
Note: Microsoft Books online is adefault reference of all articles but examples and explanations prepared byRitesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Find missing Index with DMVs in SQL Server 2005/2008/Denali

In the previous articles I saw how to find unused index sothat you can find it and drop it to improve performance of your Insert /Update/Delete statement and claim some disk space which is really useful inproduction server.
Today I will be exploring the script to find the missingindex, after finding that index; you can decide whether to create it or notbased on the requirement of your application. 
There are many important DMVs (Dynamic Management View)there in SQL Server 2005 and higher version which are keeping information youneed to know to find missing index. Following is the list of those DMVs.
sys.dm_db_missing_index_details”:  This DMV returns details about missing indexyou need to create. For more information on this, please click here.
sys.dm_db_missing_index_group_stats”: This DMV returns thesummary of benefit you would have received if you would have the particular index.For more information on this, please click here.
sys.dm_db_missing_index_groups”: This DMV returnsinformation about what missing index are contained in what missing index grouphandle. For more information on this, please click here.
sys.dm_db_missing_index_columns(Index_Handle)”:  This DMV gives you an idea about what columnsare missing in Index, it is based on the “Index_Handle” field of “Sys.dm_db_missing_index_details”DMV. For more information on this, please clickhere.
Let us run all these four DMVs to see what it has for us:
select * from sys.dm_db_missing_index_details
select * from sys.dm_db_missing_index_group_stats
select * from sys.dm_db_missing_index_groups
–43816 is oneof the I have copided from my “Index_Handle” column of
–sys.dm_db_missing_index_detailsDMV, you might get something else than 43816
select * from sys.dm_db_missing_index_columns(43816)
So these are the DMVs which will be useful in order to find missingindex, we are going to use first three of the above DMVs to find our missingindex.
Here you go!!!!
SELECT
      avg_total_user_cost *avg_user_impact * (user_seeks +user_scans) ASPossibleImprovement
      ,last_user_seek
      ,last_user_scan
      ,statementAS Object
      ,‘CREATEINDEX [IDX_’ + CONVERT(VARCHAR,GS.Group_Handle) + ‘_’ + CONVERT(VARCHAR,D.Index_Handle) + ‘_’
      + REPLACE(REPLACE(REPLACE([statement],‘]’,),‘[‘,),‘.’,) + ‘]’
      +‘ ON ‘
      + [statement]
      + ‘ (‘+ ISNULL (equality_columns,)
    + CASE WHENequality_columns IS NOTNULL ANDinequality_columns IS NOTNULL THEN ‘,’ ELSE END
    + ISNULL (inequality_columns, )
    + ‘)’
    + ISNULL (‘ INCLUDE (‘ + included_columns + ‘)’, )
      AS Create_Index_Syntax
FROM
      sys.dm_db_missing_index_groups ASG
INNER JOIN
      sys.dm_db_missing_index_group_stats AS GS
ON
      GS.group_handle = G.index_group_handle
INNER JOIN
      sys.dm_db_missing_index_details ASD
ON
      G.index_handle = D.index_handle
Order By PossibleImprovement DESC
This is just a basic advice from DMVs regarding what indexesare missing and you have to create it, finally it’s up to you based on your requirementwhether to create index or not. You have to see the table name and columnwhether it has any selectivity or not then decide whether to create that or notas more index on table might improve performance of your SELECT but it willharm other DML statements so it is always advisable to use your human skills todecide rather than leave everything on DMVs.  
These DMVs could keep information for maximum of 500indexes.
Enjoy Indexing!!!!
If you want to refer all other articles related to index, clickhere.
Reference: Ritesh Shah
http://www.sqlhub.com
Note: Microsoft Books online is adefault reference of all articles but examples and explanations prepared byRitesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile

Find unused index in SQL Server 2005/2008/Denali

If you are aware with Index well or if you have read all myprevious articles related to Index, you might aware that Index can increasethe speed of SELECT statement but can reduce INSERT/UPDATE/DELETE performanceso it is better to remove Unused index, it will not only give benefit to INSERT/UPDATE/ DELETE but it will free up some disk space resources too.
So, after this clarification you understand the requirementof deleting unused Index, right? But how to find which index has never beenused? Well I have written one small snippet of TSQL for the same which I amgoing to share with you.
Note: statistics you are going to see with below givenscript, would be refreshed and start collecting data again from zero if yourestart you server instance or database.  So, first decide your business cycle, let SQLServer collect data and then run the following script to know exact situationotherwise it may happen that some query runs regularly so you can see its statsand few run only once or twice in a month or a quarter and you don’t see itsstats and based on that you drop the index which affect the query when it startrunning at its regular time after a month or quarter. 
Here is the code which I was talking about, earlier:
–followingquery will show you which index is never used
select
      ind.Index_id,
      obj.Name as TableName,
      ind.Name as IndexName,
      ind.Type_Desc,
      indUsage.user_seeks,
      indUsage.user_scans,
      indUsage.user_lookups,
      indUsage.user_updates,
      indUsage.last_user_seek,
      indUsage.last_user_scan,
      ‘drop index [‘ + ind.name + ‘] ON [‘ + obj.name + ‘]’ as DropCommand
from
      Sys.Indexes as ind JOIN Sys.Objects as obj on ind.object_id=obj.Object_ID
      LEFT JOIN  sys.dm_db_index_usage_statsindUsage
            ON
                  ind.object_id =indUsage.object_id
                  AND ind.Index_id=indUsage.Index_id
where
      ind.type_desc<>‘HEAP’ and obj.type<>‘S’
      AND objectproperty(obj.object_id,‘isusertable’) = 1
      AND (isnull(indUsage.user_seeks,0)=0 AND isnull(indUsage.user_scans,0)=0 and isnull(indUsage.user_lookups,0)=0)
order by obj.name,ind.Name
–followingquery will show you list of ALL index in database
–along withdata how many times it get seek, scan, lookup or update 
select
      ind.Index_id,
      obj.Name as TableName,
      ind.Name as IndexName,
      ind.Type_Desc,
      indUsage.user_seeks,
      indUsage.user_scans,
      indUsage.user_lookups,
      indUsage.user_updates,
      indUsage.last_user_seek,
      indUsage.last_user_scan,
from
      Sys.Indexes as ind JOIN Sys.Objects as obj on ind.object_id=obj.Object_ID
      LEFT JOIN  sys.dm_db_index_usage_statsindUsage
            ON
                  ind.object_id =indUsage.object_id
                  AND ind.Index_id=indUsage.Index_id
where
      ind.type_desc<>‘HEAP’ and obj.type<>‘S’
      AND objectproperty(obj.object_id,‘isusertable’) = 1
order by obj.name,ind.Name
Be sure before droping any index, give it a second thoughtbefore deleting it. This is usually a good practice if you are doing this onproduction server.
if you want to refer all other articles related to index, click here.
Reference: Ritesh Shah

http://www.sqlhub.com
Note: Microsoft Books online is adefault reference of all articles but examples and explanations prepared byRitesh Shah, founder of
http://www.SQLHub.com
Ask me any SQL Server related question at my “ASK Profile