When do we specify fill factor for DBCC DBREINDEX? - sql-server

I checked over google and found that if fill factor is 0 then it uses the 100% space on index page. Otherwise we need to specify the fill factor.
My questions to experts are:
Should we leave it blank for maximum index efficiency?
I found in our some databases that fill factor is 80, 85, 90, 100 mentioned for some of the indexes. So, when should we specify fill factor as 80 or 90?
Select fill_factor,* from sys.indexes where fill_factor <> 0

THe default fillfactor is 100 out of the box (if it hasn't been changed). When fillfactor is 0, DBCC DBREINDEX uses the last value specified for the index.
Fillfactor is designed for improving index performance and data storage when the index is created, rebuilt, or defragged. By setting the fillfactor, you specify the percentage of space on each page to be filled with data, reserving free space on each page for future table growth. For example, if fillfactor is 80, then 20% of each page is left empty, providing space for new records. When that space is used up, a page split occurs.
Microsoft recommends us to use the default fillfactor in most cases. However, if you know how your table will be used, you can modify it. A fillfactor of 100 for tables that are not read-only would immediately cause a page split on an INSERT/UPDATE, so 100 is only suitable for read-only tables. Tables that have a high amount of writing should be somewhere between 50 and 70%. All other tables should be around 80 and 90, if they are mostly SELECTed rather than INSERTed and UPDATEd.
You should read up on page splitting. Also, establish a schedule for rebuilding your indexes. You also need to consider whether to cluster each index or not. For example, a clustered index with a low fragmentation percentage can be excluded from the schedule to save some time.
Some references:
Fill-factor Truth
Tips for Rebuilding Indexes

Related

Index fragmentation growing rapidly even using fillfactor

I am using SQL Server 2012, from few days I have noticed that fragmentation of some indexes are growing very rapidly. I have read different article and apply the fill factor.
First I have change the fill factor to 95 and rebuild, after one day fragmentation was about 50%. So I decrease the fill factor to 90 and then 80 but after one day fragmentation again reach to 50%.
I need some help to find out the reason for growing fragmentation and solution to fix it.
FYI, I am applying fill factor on index level, only 4-5 indexes are having this issue I have applied fill factor to other indexes as well they are working fine.
Thanks in advance.
There are many things which causes index fragmentation..some of them are below
1.Insert and Update operations causing Page splits
2.Delete operations
3.Initial allocation of pages from mixed extents
4.Large row size
SQL Server only uses fillfactor when you’re creating, rebuilding, or reorganizing an index,so even if you specify a fill factor of 70, you may still get page splits.. and further Index fragmentation is an “expected” and “unavoidable” characteristic of any OLTP environment.
So with your fill factor setting, sql server leaves some space when index is rebuilt and this helps in first scenario only and this is also subjected to your workload
So i recommend not worrying about fragmentation much unless your workload does a lot of range scans..below are some links which helps you
further you can track Pagesplits/deletes which are some of the causes for fragmentation using Perfmon counters/extended events and also using transaction log
https://dba.stackexchange.com/questions/115943/index-fragmentation-am-i-interpreting-the-results-correctly
https://www.brentozar.com/archive/2012/08/sql-server-index-fragmentation/
References :
Notes - SQL Server Index Fragmentation, Types and Solutions

Does changing fill factor on Identity column affect Merge Replication?

I have identified multiple Identity columns in a database that are set to 80 or 90%. I wish to set them all to 100%.
Does anyone know if changing the fill factor on an identity column using Merge Replication causes any issues?
FillFactor comes into picture only when an index is rebuilt by leaving the Percentage of space free set using FillFactor Setting.
With Merge replication,changes at both the sources are tracked through triggers and they are kept in sync.
When you set fillfactor to 80%,20% of the space can be still used for inserts.If you set at 100% ,you are not leaving any space ,there by you have a chance of page splits.Page splits are very expensive in terms of log growth.so there is a chance your inserts will be slower.
But with identity column,all the values will be increasing,so they will be logically added to the end of page.So setting a value of 0 or 100 should improve performance.But fill factor affects only your leaf level pages and what if you update any of the row which may cause the size to exceed the total length of page..Here is what MSDN says on this case
A nonzero fill factor other than 0 or 100 can be good for performance if the new data is evenly distributed throughout the table. However, if all the data is added to the end of the table, the empty space in the index pages will not be filled. For example, if the index key column is an IDENTITY column, the key for new rows is always increasing and the index rows are logically added to the end of the index. If existing rows will be updated with data that lengthens the size of the rows, use a fill factor of less than 100. The extra bytes on each page will help to minimize page splits caused by extra length in the rows.
Setting a Good fillFactor value depends on how your database is used..Heavy Inserts(more free should be there and fillfactor value should be less,but selects will be some what costly).Less inserts (leave fill factor at some high value)
simple search yields so many results .but you should test them first and adapt it to your scenario
FILLFACTOR is mainly used for Indexing.
Since you want to change the Fill Factor to 100.Its mean you need to drop and recreate the Index on the merge tables with Fillfactor 100.
And if in your merge replication, 'Copy Clustered Index' and 'Copy Non Clustered Index' is TRUE For all article properties, then once you recreate Index on the publisher, it will also get replicate on other subscriber.
So, if you have heavy merge tables with Index, I would recommend to implement it during offhours because Index creation will take time to replicate on subscriber.
You can check the fill factor by this query too. Yes, but as #Ragesh said, whenever we change the fill factor (Replication) will impact the performance.
Fill Factor is directly related to Indexes. Every time we all here the
word ‘Index,’ we directly relate it to performance. Index enhances
performance ‑ this is true, but there are a several other options
along with it.
SELECT *
FROM sys.configurations
WHERE name ='fill factor (%)'
Here is good article and explanation of your query.
http://sqlmag.com/blog/what-fill-factor-index-fill-factor-and-performance-part-1
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9ef72506-f1b0-4700-b836-851e9871d0a6/merge-table-indexes-fill-factor?forum=sqlreplication

FILLFACTOR on empty database

I have a system which populates an empty database with many millions of records.
The database has various types of indexes, the ones I'm worried about are:
Indices on foreign keys. These are non-clustered, and not necessarily inserted in sequential order.
Indices on BINARY(32) fields. These are content hashes and not ordered at all. Basically, these are like GUIDS and not sequential.
So as the data is bulk-inserted, there is significant fragmentation of these indices.
Question 1: if I set FILLFACTOR=75 to these indices when database is created, will it have any effect at all as the data is inserted? It seems FILLFACTOR has effect after data is created not before. Or will new index pages be allocated with original fillfactor setting?
Question 2: what other recommended strategies can I use to make sure these indices perform optimally?
Question1:
Fill factor is used only when indexes are rebuilt,SQL doesnt try to store pages based on fill factor while doing inserts.
Question2:
It depends on what you are saying as optimal.On a minimal you can check whether your indexes are usefull and your queries are using your indexes.There are tons of best practices around indexes like selective first key,small keys..
Its good to search for any thing about indexes from Kimberly Tripp and DBA.SE
References:
http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2530-fill-factor/
http://www.sqlskills.com/blogs/kimberly/category/indexes/
Check the index fragmentation as well as the write/read ration. If the write/read ratio is very high AND you see fragmentation, you can experiment with adding a fillfactor during index rebuild operation.
The amount of fill-factor really depends on your fragmentation you are seeing. If you see 0-20% fragmentation (and these happened over a period of time), you may not want any fill-factor. If you see 20-40% fragmentation, you may try 90%.
Lastly get a good index maintenance plan. Ola Hallengren's index script is excellent.
NB: Above suggestions are just suggestions - your

How to find out SQL Server table's read/write statistics?

Is there a way to find a statistics on table read and write count on SQL Server 2005/2008?
I am specifically looking for DMVs/DMFs without using triggers or audits.
The goal here is to find out appropriate fill factor for indexes - got an idea from this article (Fill Factor Defined).
[UPDATE] There is a follow up question on ServerFault How to determine
Read/Write intensive table from
DMV/DMF statistics
Following query can be used to find number of read and writes on all tables in a database. This query result can be exported to CSV file and then using excel formulas you can easily calculate read/write ratio. Very useful while planning indexes on a table
DECLARE #dbid int
SELECT #dbid = db_id('database_name')
SELECT TableName = object_name(s.object_id),
Reads = SUM(user_seeks + user_scans + user_lookups), Writes = SUM(user_updates)
FROM sys.dm_db_index_usage_stats AS s
INNER JOIN sys.indexes AS i
ON s.object_id = i.object_id
AND i.index_id = s.index_id
WHERE objectproperty(s.object_id,'IsUserTable') = 1
AND s.database_id = #dbid
GROUP BY object_name(s.object_id)
ORDER BY writes DESC
sys.dm_db_index_physical_stats (size and fragmentation)
sys.dm_db_index_usage_stats (usage, number of scans/seeks/updates etc)
sys.dm_db_index_operational_stats (current activity on index)
Remember 'table' means the clustered index or the 'heap'.
To determine an appropriate fill factor for a table's indexes, you need to look at the number of page splits occuring. This is shown in sys.dm_db_index_operational_stats:
Leaf allocation count: Total number of page splits at the leaf level of the index.
Nonleaf allocation count: Total number of page splits above the leaf level of the index.
Leaf page merge count: Total number of page merges at the leaf level of the index.
After doing a bit of digging, I've seen a few posts that say the page split numbers from the DMV's are not that useful (I haven't personally confirmed this), but there is also a performance counter "page splits/sec" (but it's is only at SQL Server instance level).
I use the rule of thumb that ordinary tables use the default 90% fill factor, high insert tables somewhere between 70 - 85% (depending on row size). Read only tables can utilise a fill factor of 100%
If you have a good clustered index (i.e., ever increasing, unique, narrow) then the real determining issues for Fill Factor are how the table is updated and the data types of the columns.
If the columns are all fixed size (e.g., integer, Decimal, Float, Char) and non-nullable then an update cannot increase the storage required for a row. Given the good clustered index you should pick a Fill Factor of 90+ even 100 since page splits won't happen.
If you have a few variable length columns (e.g. a Varchar to hold User Name) and the columns are seldom updated after insert then you can still keep a relatively high Fill Factor.
If you have data that is highly variable in length (e.g., UNC paths, Comment fields, XML) then the Fill Factor should be reduced. Particularly if the columns are updated frequently and grow (like comment columns).
Non-Clustered indexes are generally the same except the index key may be more problematic (non unique, perhaps not ever increasing).
I think sys.dm_db_index_physical_stats gives the best metrics for this but it is after the fact. Look at the avg/min/max record size, avg frag size, avg page space used to get a picture of how the index space is being used.
HTH.

SQL Server Performance and clustered index values

I have a table myTable with a unique clustered index myId with fill factor 100%
Its an integer, starting at zero (but its not an identity column for the table)
I need to add a new type of row to the table.
It might be nice if I could distinguish these rows by using negative values of myId.
Would having negative values incur extra page splitting and slow down inserts?
Extra Background:
This table exists as part of the etl for a data warehouse that gathers data from disparate systems. I now want to accomodate a new type of data. A way for me to do this is to reserve negative ids for this new data, which will thus be automatically clustered. This will also avoid major key changes or extra columns in the schema.
Answer Summary:
Fill factors of 100% will noramlly slow down the inserts. But not inserts that happen sequentially, and that includes the sequntial negative inserts.
Besides the practical administration points you already got and the suspect dubious use of negative ids to represent data model attributes, there is also a valid question here: give a table with int ids from 0 to N, inserting new negative values where would those value go and would they cause additional splits?
The initial rows will be placed on the clustered index leaf pages, row with id 0 on first page and row with id N on the last page, filling the pages in between. When the first row with value of -1 is inserted, this will sort ahead of row with id 0 and as such will add a new page to the tree (will allocate an extent of 8 pages actually, but that is a different point) and will link the page in front of the leaf level linked list of pages. This will NOT cause a page split of the former first page. On further inserts of values -2, -3 etc they will go to the same new page and they will be inserted in the proper position (-2 ahead of -1, -3 ahead of -2 etc) until the page fills. Further inserts will add a new page ahead of this one, that will accommodate further new values. Inserts of positive values N+1, N+2 will go at the last page and be placed in it until it fills, then they'll cause a new page to be added and will start filling that page.
So basically the answer is this: inserts at either end of a clustered index should not cause page splits. Page splits can be caused only by inserts between two existing keys. This actually extends to the non-leaf pages as well, an index at either end of the cluster may not split a non-leaf page either. I do not discuss here the impact of updates of course (they can can cause splits if the increase the length of a variable length column).
Lately has been a lot of talk in the SQL Server blogosphere about the potential performance problems of page splits, but I must warn against going to unnecessary extremes to avoid them. Page splits are a normal index operation. If you find yourself in an environment where the page split performance hit is visible during inserts, then you'll be probably worse hit by the 'mitigation' measures because you'll create artificial page latch hot spots that are far worse as they'll affect every insert. What is true is that prolonged operation with frequent splits will result in high fragmentation which impacts the data access time. I say that is best mitigated with off-peak periodical index maintenance operation (reorganize). Avoid premature optimizations, always measure first.
Not enough to notice for any reasonable system.
Page splits happen when a page is full, either at the start or at the end of the range.
As long as you regular index maintenance...
Edit, after Fill factor comments:
After a page split wth 90 or 100 FF, each page will be 50% full. FF = 100 only means an insert will happen sooner (probably 1st insert).
With a strictly monotonically increasing (or decreasing) key (+ve or -ve), a page split happens at either end of the range.
However, from BOL, FILLFACTOR
Fill
Adding Data to the End of the Table
A nonzero fill factor other than 0 or
100 can be good for performance if the
new data is evenly distributed
throughout the table. However, if all
the data is added to the end of the
table, the empty space in the index
pages will not be filled. For example,
if the index key column is an IDENTITY
column, the key for new rows is always
increasing and the index rows are
logically added to the end of the
index. If existing rows will be
updated with data that lengthens the
size of the rows, use a fill factor of
less than 100. The extra bytes on each
page will help to minimize page splits
caused by extra length in the rows.
So does, fillfactor matter for strictly monotonic keys...? Especially if it's low volume writes
No, not at all. Negative values are just as valid as INTegers as positive ones. No problem. Basically, internally, they're all just 4 bytes worth of zeroes and ones :-)
Marc
You are asking the wrong question!
If you create a clustered index that has a fillfactor of 100%, every time a record is inserted, deleted or even modified, page splits can occur because there is likely no room on the existing index data page to write the change.
Even with regular index maintenance, a fill factor of 100% is counter productive on a table where you know inserts are going to be performed. A more usual value would be 90%.
I'm concerned that this post may have taken a wrong turn, in that there seems to be an underlying design issue at work here, irrespective of the resultant page splits.
Why do you need to introduce a negative ID?
An integer primary key, for example, should uniquely indentify a row, it's sign should be irrelevant. I suspect that there may be a definition issue with the primary key for your table if this is not the case.
If you need to flag/identify the newly inserted records then create a column specifically for this purpose.
This solution would be ideal because you may then be able to ensure that your primary key is sequential (perhaps using an Identity data type, although not essential), thereby avoiding issues with page splits (on insert) altogether.
Also, to confirm if I may, a fill factor of 100% for a clustered index primary key (identity integer for example), will not cause page splits for sequential inserts!

Resources