I have a test scenario where I have added fill-factor
= 90 to a clustered index over a random generated GUID primary key.
If I create the table without fill-factor
= 90 then the number of page splits is initially 31 for 3974 rows and splits occur with every subsequent insert. When I include the fill-factor
= 90 the number of splits on population rises to 35 but splits stop happening with every subsequent insert. All good so far!
The problem is that when I add a non-clustered index although the clustered index still indicates a fill-factor
of 90% the initial insert is back to 31 splits and splits are happening again on every subsequent insert indicating that the fill-factor
is being ignored.
Does anyone have an idea as to why this might be happening?
/*
scenarios:
1. Create table #Test02 without fillfactor, populate and observe 37 page splits occured, insert two rows at a time and observe page splits occurring
2. Drop and create table #Test02 with filfactor = 90, populate and observe 40 page splits occurred, insert two rows at a time and observe that page splits do not occurr
3. Drop and create table #Test02 with filfactor = 90, insert two rows then populate, observer 38 page splits occurred, insert two rows at a time and observe page splits occurring
4. Drop and create table #Test02 with filfactor = 90, create index IX_#Test02_ProductName, populate and observe 37 & 35 page splits occurred, insert two rows at a time and observe that page splits occur on PK
5. Rebuild index PK_Test02, insert two rows at a time and observe that page splits do not occurr
Conclusion: On an empty table with a PK FF = 90 SQL preserves the fill factor
*/
--non-sequential index table
IF OBJECT_ID('tempdb.dbo.#Test02') IS NOT NULL DROP TABLE #Test02
--CREATE TABLE #Test02(ID uniqueidentifier default newid(), ProductName nvarchar(150), CONSTRAINT PK_Test02 PRIMARY KEY CLUSTERED (ID))
CREATE TABLE #Test02(ID uniqueidentifier default newid(), ProductName nvarchar(150), CONSTRAINT PK_Test02 PRIMARY KEY CLUSTERED (ID) WITH (FILLFACTOR = 90))
--ALTER INDEX PK_Test02 ON #Test02 REBUILD WITH (FILLFACTOR = 90);
IF EXISTS (SELECT * FROM tempdb.sys.indexes WHERE name = N'IX_#Test02_ProductName') DROP INDEX IX_#Test02_ProductName ON #Test02
CREATE INDEX IX_#Test02_ProductName ON #Test02(ProductName)
--populate script
INSERT #Test02(ProductName)
SELECT TOP 4000 COALESCE(O1.name,O2.name)
FROM master.sys.objects O1
CROSS JOIN master.sys.objects O2
--two row insert
INSERT #Test02(ProductName) VALUES(N'Straight Banana'),(N'Bent Banana')
--observe page splits
SELECT ios.index_id
, o.name as object_name
, i.name as index_name
, ios.leaf_allocation_count as page_split_for_index
, ios.nonleaf_allocation_count page_allocation_caused_by_pagesplit
, ios.leaf_insert_count
, i.fill_factor
FROM tempdb.sys.dm_db_index_operational_stats(db_id(N'db_name'), null, null, null) ios
JOIN tempdb.sys.indexes i on ios.index_id = i.index_id AND ios.object_id = i.object_id
JOIN tempdb.sys.objects o on ios.object_id = o.object_id
WHERE o.type_desc = N'user_table'
AND o.name like N'#test02%'