Fill Factor is telling how much space, from a page, can be used with storing records.
It’s possible only for indexes.
100% = 0% = to use the hole page = 8kbytes.
Having a different fill factor then 100%, it means you preserve some free space.
The fill factor is “activated” when you create an index, rebuild an index, reorg an index.
When you do create, rebuild, you can set a different value for the fill factor
When you do reorg, the value of the fill , it’s the used/default value.
Depending of your scenariou you can have a 100% or less fill factor:
- if it’s doing inserts at the end of the index (with a identity clustered column ) and no update of a varchar data type columns = then use 100% fill factor
- if it’s doing random insert (like GUID as cluster key column) or doing update of a variable data type length = use a different , a low fill factor. This should be monitor (1 per week or per 2weeks or 1 per month) to see if you still have a high number of page split. If yes, reduce again the fill factor with 5% (or 10%) and re-monitor it.
Having a lower fill factor, combine with your scenariu , you will have:
PRO:
- less page splits
CONS
- additional storage
- additional pages to be read
Example:
We are using two tables , same fields , but one will have fill_factor = 100, one will have fill_factor =60.
drop table if exists dbo.fillFact_Full;
create table dbo.fillFact_Full
(
id int not null,
myChar char(985) not null,
myVarChar varchar(500) null
)
GO
CREATE UNIQUE CLUSTERED INDEX idx_fillFact_Full_id ON dbo.fillFact_Full
(id);
GO
drop table if exists dbo.fillFact_60;
create table dbo.fillFact_60
(
id int not null,
myChar char(985) not null,
myVarChar varchar(500) null
)
GO
CREATE UNIQUE CLUSTERED INDEX idx_fillFact_60_id ON dbo.fillFact_60
(id);
GO
Initial setup, insert 20 records, and the two tables will be identical.

Now, activate the fill factor = 60 for table 2, “fillFact_60” , and fill factor = 100 for the table “fillFact_FULL”, and look at the space and pages used:


So, definitely , the space used is much more for the one with fill factor = 60
What about pages read, when doing a select (more then 1 record, like select *)

Again, more logical reads for the one with fill factor = 60.
Let’s look at the location of each record in pages ; for this will use undocumented function : %%physloc%% and sys.fn_PhysLocCracker(%%physloc%%)

And now let’s update some records, or insert in a particular page, base on key clustered value.
–update some records with id = 9 ,12
–for id = 9,12 , page = 392
update dbo.fillFact_Full
set myVarChar = LEFT(REPLICATE(‘update:’ + CAST(id AS VARCHAR(50)) ,500),500)
where id IN( 9 ,12)
–for id = 9,12 , page = 400
update dbo.fillFact_60
set myVarChar = LEFT(REPLICATE(‘update:’ + CAST(id AS VARCHAR(50)) ,500),500)
where id IN( 9 ,12)
–see the location of each record:
select flc.*,f.* from dbo.fillFact_Full as f CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) as flc
select flc.*,f.* from dbo.fillFact_60 as f CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)as flc

We can see, that in table with fill factor = 100 , one record with id = 9 was able to store the additional information, but for the record with id = 12 ,no; it needed a new page , pageid = 465.Additional , it’s moving the half of records, from id = 12 till 24.
For the table with fill factor = 60, both update were able to be stored in the same page. page id = 400
For insert , the same : adding some records will have the same effect as update.

code can be found here
S


