Sql Server Faq

June 28, 2010

Fragmentation should not be the only factor which decides the Rebuild Index

Filed under: Uncategorized — @ 3:02 pm

Until now I was under the impression that fragmentation in the Index is the only factor which decides whether we should rebuild the index.

 

As a rule of thumb we always recommend that when the avg_fragmentation_in_percent in the view  sys.dm_db_index_physical_stats  is between 5 and 30

We should reorganize the index and when the fragmentation is greater than 30 we should rebuild the index.

(Further reading:  http://technet.microsoft.com/en-us/library/ms189858.aspx)

 

However recently my observation showed me that avg_fragmentation_in_percent is not the only factor which should decide the rebuild the index.

 

The rebuild of the index is also decided by depth of the index and in this blog post I will be talking about the same.

 

We all are aware that Clustered Index Keys should preferably have sequential inserts to avoid fragmentation caused due to page splits. However sequential inserts can have its own problem. One of which is blogged by Amit Banerjee

 

Sequential inserts can lead to logical fragmentation  which is not detected  as physical fragmentation by sys.dm_db_index_physical_stats. Now what do I mean by logical Fragmentation?

 

We all know indexes in sql server are organized as B-tree structure using Balanced Tree Algorithm. However as data gets inserted in the index, the Balanced tree structure is no longer maintained and the B-Tree structure goes out of shape which leads to Logical Fragmentation.

 

So even in sequential inserts as data is inserted into the index the Balanced Tree structure stretches towards right and Node splits occurs which increases the depth of the index.

 

The depth of the index is the maximum distance between the root node and the leaf nodes. In the below case Initially when the index was built the depth of index  the depth of index is 3 however after the node splits the depth of the index increases to 4.

 

 

 

 

 

Practical Example

===============

 

use tempdb

go

create table Indexdepth(a int, b char(8000))

go

 

DECLARE @i int

set @i = 0

while (@i < 10000)

begin

insert into Indexdepth values(@i,‘Indexdepth’)

set @i = @i + 1

end

 

create unique clustered index IDX_CLUSTERED on Indexdepth(a)

 

select * from sys.dm_db_index_physical_stats(DB_ID(‘tempdb’),OBJECT_ID(‘dbo.Indexdepth’),1,1,null)

 

—— Avg_fragmentation_in_percent 0 and index_depth 3

 

–Let us do some sequential inserts on the index

 

DECLARE @i int

set @i = 100

while (@i < 500000)

begin

insert into Indexdepth values(@i,‘Indexdepth’)

set @i = @i + 1

end

 

select * from sys.dm_db_index_physical_stats(DB_ID(‘tempdb’),OBJECT_ID(‘dbo.Indexdepth’),1,1,null)

 

—— Avg_fragmentation_in_percent 0.4375 and index_depth 4 

 

 

So in the above example we observed that after doing around some sequential inserts the fragmentation as reported by sys.dm_db_index_physical_stats is only 0.4% which is good and does not qualify it for the Reindexing as per our rule.

 

However if you observe now the depth of the index has increased from 3 to 4.

 

Now what is the implication of the depth of the index?

 

Depth of the index is nothing but the minimum number of pages read when you perform Clustered Index Seek.  So if the index depth is 4  a clustered index seek operation will need to do 4 logical reads atleast as compared to 3 when the index depth is 3.

 

Again 1 additional logical read is fine so long as the index is not involved in Key Lookup operation which is Nonclustered index seek followed by Clustered index seek. i.e following operation

 

Let’s say  if the Index Seek qualifies 100 rows then for each row we have a clustered index seek. So there will be 100 lookups and for each lookup there may be 1 additional logical read. So in all there might be 100 extra logical reads.

 

In the previous example after the index is rebuild , the index_depth is reduced to 3 again.

 

So to conclude, Indexes should be rebuild not only when there is more than 30% fragmentation but also when the index depth is higher than 3.

 

Not everyone might hit the above issue but I thought I should still share it with the people who are not aware of Importance of index depth

Share/Save/Bookmark

June 20, 2010

Fragmentation on Index in Sql Server

Filed under: Uncategorized — @ 6:40 am

 

Hi All,

It has being quite some time since I added a new post since off late I am not spending much of time on research. But I have started my research again and in this post I will be talking about Fragmentation of Index which occurs due to split of root node of an index.

We all know that in Sql server, Index is organized in the form of B-tree structure wherein the data lies on the leaf level (also called leaf nodes) followed by intermediate node and finally root node at the top.

Indexes are performance boosters for Select queries however the same indexes are overhead for DML operations.  Also as data is inserted/updated and deleted the index tend to get Fragmented.

In Sql Server we have 2 types of Fragmention viz Logical Fragmentation and Extent Fragmentation.

Logical Fragmentation happens when the index goes out of shape i.e Balanced Tree structure is distorted while Extent Fragmentation is caused due to page splits when the new pages are allocated in the new extent which might be different area of the datafile or even different datafile of a filegroup.

Fragmentation is mainly caused due to Page Splits which occurs either at the leaf node or intermediate node or root node. Fragmentation at the leaf nodes can be fixed using reorganize of Index however page splits at intermediate node or root node causes depth of the index to increase which is more detrimental from the point of view performance. Since every access path to the leaf node of index goes through root and intermediate node.

So in the following script I have tried to demo how root node of index splits and in order to fix the fragmentation we have rebuild the index because reorganize of index operate s at leaf level but does not operate at root level and intermediate.

Note: In Sql 2000 fragmentation of the index is monitored using DBCC SHOWCONTIG while starting sql 2005 fragmentation is monitored using a DMV sys.dm_db_index_physical_stats

create table test(a int, b char(3950))
go

–truncate table test

declare @i int
set @i = 0
while @i < 100000
    begin
         
insert into test(a,b) values(@i, ‘test’)
          set @i= @i+1;
end

create clustered index test_idx on test(a)
go

——Find the first root page of the index

select first_page, CONVERT (INT, SUBSTRING (root_page, 4, 1) + SUBSTRING (root_page, 3, 1) + SUBSTRING (root_page, 2, 1) + SUBSTRING (root_page, 1, 1)) AS ‘rootPage’,data_pages from sys.system_internals_allocation_units inner join sys.partitions on container_id = partition_id where object_id = OBJECT_ID(‘test’)

—– See the fragmentation, page count  and index _ depth  on the clustered index  initially

select * from sys.dm_db_index_physical_stats(1,OBJECT_ID(‘test’),1,1,NULL)

 index_type_desc   index_depth index_level avg_fragmentation_in_percent fragment_count       avg_fragment_size_in_pages page_count

 —————— ———– ———– —————————- ——————– ————————– ———

 CLUSTERED INDEX    3           0           0.01                         675                  74.0755555555556           50001   

———- DBCC PAGE on the root page shows that points to 114 intermediate pages

dbcc TRACEON(3604)

DBCC PAGE(1,1,50978,3)      root page giving pointers to next intermediate level

1 root page + 114 intermediate page

FileId PageId      Row    Level  ChildFileId ChildPageId a (key)     UNIQUIFIER (key) KeyHashValue

—— ———– —— —— ———– ———– ———– —————- —————-

1      50978       0      2      1           50976       NULL        NULL             NULL
1      50978       1      2      1           50977       1010        0                NULL
1      50978       2      2      1           50979       2020        0                NULL
1      50978       3      2      1           50980       3030        0                NULL
1      50978       4      2      1           50981       4040        0                NULL
1      50978       5      2      1           50982       5050        0                NULL
1      50978       6      2      1           50983       6060        0                NULL
1      50978       7      2      1           50984       7070        0                NULL
1      50978       8      2      1           50985       8080        0                NULL

—- insert few more rows to introduce fragmentation

declare @i int
declare @j int
set @i = 0
set @j = 4
while @i < 110000

begin
insert into test(a,b) values(4, ‘test’)
set @i= @i+1;
end

—- check fragmentation, page_count and depth of the index again

select * from sys.dm_db_index_physical_stats(1,OBJECT_ID(‘test’),1,1,NULL),index_type_desc   index_depth index_level avg_fragmentation_in_percent fragment_count       avg_fragment_size_in_pages page_count    

—————————– ———– —————————- ——————– ————————– ———

CLUSTERED INDEX   4           0           0.368175124088653            1095                 100.458447488584           111915        

—Depth of the index is now 4

— Letz check the root_page again for the table

select first_page, CONVERT (INT, SUBSTRING (root_page, 4, 1) + SUBSTRING (root_page, 3, 1) + SUBSTRING (root_page, 2, 1) + SUBSTRING (root_page, 1, 1)) AS ‘rootPage’,data_pages from sys.system_internals_allocation_units inner join sys.partitions on container_id = partition_id where object_id = OBJECT_ID(‘test’)

— Root Page is changed since it was split and hence we got new depth in the index. The previous root page is now at Level 2 and new root page at Level 3

DBCC PAGE(1,1,141458,3)      root page giving pointers to next 2 intermediate page which is inturn giving pointers to another pages

156 intermediate pages(Level 1) + 2 intermediate  page (Level 1)+ 1 root page

dbcc ind(master,test,1)

 

PageFID PagePID        IAMFID IAMPID      ObjectID    IndexID  PartitionNumber PartitionID     iam_chain_type PageType IndexLevel NextPageFID NextPagePID PrevPageFID PrevPagePID

——- ———–    —— ———– ———– ———– ————- ——————– ——————-

1          620                  NULL    NULL    1403152044    1          1                      7.20576E+16   In-row data      10            NULL    0          0          0          0
1          42050              1          620      1403152044    1          1                      7.20576E+16   In-row data      2          2            1          141459            0          0
1          141458                        1          620      1403152044    1          1                      7.20576E+16   In-row data      2            3          0          0          0          0
1          141459                        1          620      1403152044    1          1                      7.20576E+16   In-row data      2            2          0          0          1          42050

— Let us observe the changes in Fragmentation after reorganizing the index

ALTER INDEX test_idx On TEST REORGANIZE

— No change observed in depth of the index or Fragmentation percent but only page is reduced in the total page_count

select * from sys.dm_db_index_physical_stats(1,OBJECT_ID(‘test’),1,1,NULL)

 

index_type_desc   index_depth index_level avg_fragmentation_in_percent fragment_count       avg_fragment_size_in_pages page_count  

—————– ———– ———– —————————- ——————– ————————– ————-

CLUSTERED INDEX   4           0           0.322569115570885            378                  296.068783068783           111914      

 

— We checked the root page and number of intermediate pages . Those remain the same.

DBCC PAGE(1,1,141458,3)      root page giving pointers to next 2 intermediate page which is inturn giving pointers to another pages

156 intermediate pages(Level 1) + 2 intermediate  page (Level 1)+ 1 root page

  Let us observe the changes in the Fragmentation after rebuilding the index

ALTER INDEX test_idx ON TEST REBUILD

— The depth of the index is reduced to 3 and Fragmentation on the index is almost reduced to 0

index_type_desc  index_depth index_level avg_fragmentation_in_percent fragment_count       avg_fragment_size_in_pages page_count

—————- ———– ———– —————————- ——————– ————————– ———–

CLUSTERED INDEX  3           0           0.01                         1477                 75.77048070413             111913    

–ROOT PAGE IS NOW CHANGED again to a new value and resides at Level 2 while there are

DBCC PAGE(1,1,156138 ,3)

277 intermediate pages (Level 1) + 1 root pages

 

Hope this clarifies how Fragmentation occurs in sql server!!!

 

 

Regards
Parikshit

Share/Save/Bookmark

February 11, 2009

SQL SERVER 2005 INSTANCE FAILING TO INSTALL AFTER TRYING TO REINSTALL WITH ERROR 1603

Filed under: Uncategorized — @ 9:13 am

 

Many times we need to reinstall a sql server instance due to number of reason.

Whenever you reinstall the sql server instance the success of the installation of the new sql server instance primarily depends on the whether the previous uninstall of the sql server was clean so that all the registry keys and the related folders are deleted.

If the un-installation is done primarily from GUI and if it is successful we can say that the uninstall was clean, however if you go for manual un-installation you need to ensure that all the related registry keys and folders are deleted. We can refer to the following KB article to manually cleanup the sql server instance

http://support.microsoft.com/kb/290991

However if the previous un-installation was not clean, when trying to reinstall the sql server instance the installation may fail with error 1603.

As we have mentioned in our previous post whenever an setup installation fails we need to first check the Summary.txt to check for the Error Message which caused the failure.

——————————————————————————–
Machine : NODE01
Product : Microsoft SQL Server 2005
Product Version : 9.00.1399.06
Install : Failed
Log File : C:\Program Files\Microsoft SQL Server\90\Setup Bootstrap\LOG\Files\SQLSetup001_NODE01_SQL.log
Error Number : 1603
——————————————————————————–
Machine : NODE02
Product : Microsoft SQL Server 2005
Product Version : 9.00.1399.06
Install : Failed
Log File : \\NODE01\C$\Program Files\Microsoft SQL Server\90\Setup Bootstrap\LOG\Files\SQLSetup001_NODE02_SQL.log
Error Number : 1602
——————————————————————————–

 

We checked the SQLSetup001_NODE01_SQL.log which is mentioned above and looked for “Return Value 3” and reached the following part of the log which leads us to the root cause of the error

 

SQLSetup001_NODE01_SQL.log

=======================

MSI (s) (34:E4) [02:35:53:642]: Doing action: CAResolveInstanceName.68C6D15C_77E0_11D5_8528_00C04F68155C
Action ended 02:35:53: SQLLicensing.D20239D7_E87C_40C9_9837_E70B8D4882C2. Return value 1.
MSI (s) (34:A0) [02:35:53:642]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI32F.tmp, Entrypoint: ResolveInstanceName
Action start 02:35:53: CAResolveInstanceName.68C6D15C_77E0_11D5_8528_00C04F68155C.
FTECa.DLL: INFO: FTE: ResolveInstanceName(), Entering…
FTECa.DLL: INFO: FTE: This is NOT an Exchange Server install…
FTECa.DLL: INFO: ResolveInstanceName: FTEInstName obtained: TMSDERIV_PROD
FTECa.DLL: INFO: ResolveInstanceName: FTERudeInstName obtained: MSSQL.8
FTECa.DLL: INFO: LookupInstanceId: Iterating the key: 1
FTECa.DLL: INFO: LookupInstanceId: Iterating rude name: MSSQL.1
FTECa.DLL: INFO: LookupInstanceId: Iterating the key: 2
FTECa.DLL: INFO: LookupInstanceId: Iterating rude name: MSSQL.2
FTECa.DLL: INFO: LookupInstanceId: Iterating the key: 3
FTECa.DLL: INFO: LookupInstanceId: Iterating rude name: MSSQL.4
FTECa.DLL: INFO: LookupInstanceId: Iterating the key: 4
FTECa.DLL: INFO: LookupInstanceId: Iterating rude name: MSSQL.6
FTECa.DLL: INFO: LookupInstanceId: Iterating the key: 5
FTECa.DLL: ERROR: LookupInstanceId: RegQueryValueEx(RudeName) failed. Err = 2
Action ended 02:35:53: CAResolveInstanceName.68C6D15C_77E0_11D5_8528_00C04F68155C. Return value 3.
Action ended 02:35:53: INSTALL. Return value 3.

From the above error we see that setup is unable to resolve the GUID 68C6D15C_77E0_11D5_8528_00C04F68155C into the sql server instance name and hence the setup was failing with error 1603.

Setup was looking at the registry location HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSFTESQLInstMap to resolve the GUID to the Instance Name.

We checked the registry location HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSFTESQLInstMap and found there was wrong mapping for GUID 68C6D15C_77E0_11D5_8528_00C04F68155C.

 

IMPORTANT : This resolution contains information about modifying the registry. Before you modify the registry, make sure to back it up and make sure that you understand how to restore the registry if a problem occurs. For information about how to back up, restore, and edit the registry, click the following article number to view the article in the Microsoft Knowledge Base:

256986 Description of the Microsoft Windows Registry

 

Resolution
========

So to resolve the issue we renamed the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSFTESQLInstMap  to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSFTESQLInstMap.old  and started the installation and the install ran fine without any errors.

 

Note:

This post should not be treated as the Microsoft’s Recommendation or Resolution to the problem, it is only a workaround which worked in our environment and so we would like to share it.

 cmeb76jvk4



 

 

Development Blog

 

 

Share/Save/Bookmark

January 18, 2009

Queries MAY Appear to RUN SLOW on SQL SERVER COMPACT EDITION v3.1 Database

Filed under: Uncategorized — @ 9:19 am

While running your application on SQL CE v3.1 databases you may observe slowness in the performance of some of the queries especially those which involve querying the primary key.

In Sql server databases when you create a Primary Key on a column of a table, it will automatically create a unique index on the column which prevent duplicate entries to be inserted on the primary key column. This Unique index which is generated by Sql server engine automatically are called as the system generated indexes.

Ideally the statistics should be created automatically on the system generated indexes but we have observed that on SQL CE v3.1 databases statistics are not automatically created on the system generated indexes.

Due to the absence of statistics optimizer may select wrong execution which can ultimately lead to poor performance of the sql queries.

To improve the performance we need to manually create the statistics on system generated indexes using following query

CREATE STATISTICS ON <table-name> WITH FULLSCAN,NORECOMPUTE

FULLSCAN ensure that entire table is scanned to generate the statistics and we have not used any sampling.

NORECOMPUTE is used to indicate that Statistics will be updated manually and should not be triggered automatically by optimizer.

Once the statistics are created we need to manually update the statistics periodically using the following command

UPDATE STATISTICS ON <table-name> WITH FULLSCAN,NORECOMPUTE.

The above issue does not occur in SSCE v3.5 in which the statistics are automatically created on system generated indexes and hence the same query might appear to run fast on SSCE v3.5 while it appears to run slow on SSCE v3.1

If after creating and updating the statistics on the system generated indexes manually you still observe slowness in performance you might considering using other query tuning option

 

 

 

 

Share/Save/Bookmark

January 15, 2009

SQL SERVER 2005 RESOURCE FAILS TO COME ONLINE ON CLUSTER AFTER CHANGING THE SAN DRIVE TO ADD MORE DISK SPACE

Filed under: Uncategorized — @ 7:26 am

We have observed a number of issue now where in clustered instance of sql server 2005 fails to come online after performing changing on shared disk on a cluster.

As mentioned in my previous posts if the sql server fails to come online we need to start troubleshooting by looking at the sql server error log. So we checked the sql server error log and  observed the following error

2009-01-11 21:10:06.96 Server      Error: 26054, Severity: 16, State: 1.
2009-01-11 21:10:06.96 Server      Could not find any IP address that this SQL Server instance depends upon.  Make sure that the cluster service is running, that the dependency relationship between SQL Server and Network Name resources is correct, and that the IP addresses on which this SQL Server instance depends are available.  Error code: 0×103.
2009-01-11 21:10:06.96 Server      Error: 17182, Severity: 16, State: 1.
2009-01-11 21:10:06.96 Server      TDSSNIClient initialization failed with error 0×103, status code 0xa.
2009-01-11 21:10:06.96 Server      Error: 17182, Severity: 16, State: 1.
2009-01-11 21:10:06.96 Server      TDSSNIClient initialization failed with error 0×103, status code 0×1.
2009-01-11 21:10:06.96 Server      Error: 17826, Severity: 18, State: 3.
2009-01-11 21:10:06.96 Server      Could not start the network library because of an internal error in the network library. To determine the cause, review the errors immediately preceding this one in the error log.
2009-01-11 21:10:06.96 Server      Error: 17120, Severity: 16, State: 1.
2009-01-11 21:10:06.96 Server      SQL Server could not spawn FRunCM thread. Check the SQL Server error log and the Windows event logs for information about possible related problems.

As seen from the above Error 26054 message which says that cluster service is unable to find the dependency between the sql server instance and the sql network resource name.

We checked the Cluster Administrator for the sql server resource and found that the dependency exists between the sql server resource and sql network name but still we receive the error.

Cause
=====

We checked the Registry Location HKLM\Cluster\Resources\<SQL Server GUID>\Parameters

The values InstanceName and VirtualServerName were missing from the keys below:

HKLM\Cluster\<SQL Server GUID>\Parameters
HKLM\Cluster\<SQL Agent GUID>\Parameters

The above registry keys are used by the cluster administrator to connect and start the sql server service. So the Cluster Administrator was not able to connect and start the sql server  resource and hence we receive the above error

Resolution
========

IMPORTANT : This resolution contains information about modifying the registry. Before you modify the registry, make sure to back it up and make sure that you understand how to restore the registry if a problem occurs. For information about how to back up, restore, and edit the registry, click the following article number to view the article in the Microsoft Knowledge Base:

256986 Description of the Microsoft Windows Registry

We added the following registry values in the Parameters registry key:

For a named instance of SQL Server:

• InstanceName
Value Name: InstanceName
Value Type: REG_SZ
Value Data: <instance name of the named instance>

• VirtualServerName
Value Name: VirtualServerName
Value Type: REG_SZ
Value Data: <Virtual server name of the instance>

Once we added the registry keys we were able to bring the sql server online on Node1. 

We failed the instance over to Node2 we checked the above registry keys and found they were missing, so we added missing keys and rebooted both the servers of the clusters.

After rebooting the server the sql server resources came online fine without any errors

 

Note:

This post should not be treated as the Microsoft’s Recommendation or Resolution to the problem, it is only a workaround which worked in our environment and so we would like to share it.

 

Share/Save/Bookmark

Newer Posts »

Powered by WordPress