If you’re noticing a significant drop in performance, as well as frequent index fragmentation, you might have an issue with page splits, especially if your fill factor is set to default on all of your indexes.
What Are Page Splits?
Page splits occur when there is insufficient free space on a data page to insert or update data. During a page split, SQL Server takes a percentage of the data and puts it on a new data page before inserting or updating the new value.
To illustrate this, imagine that you have a set of bookshelves filled with books arranged alphabetically, and you need to add a book that starts with “M”. Let’s say it’s supposed to go in the middle of one of the shelves. Since the shelves are completely filled and you want to keep the books in alphabetical order, you take out about half the books—including the ones that start with “M”—on this particular shelf, put them on a new shelf, and add the new book there. Now, you have an extra shelf that’s only half full, along with one of the existing shelves that’s also only half full.
Imagine doing this many, many, many times. It costs time and energy (you’re probably exhausted just thinking about this analogy), plus valuable storage since there is a whole lot of wasted space on those half-full shelves. In addition, you can’t even put the new shelves where they’re “supposed” to go, since the shelves can’t be moved around, only added at the end of the row.
This is how page splits work and how they can lead to index fragmentation (since the data is being moved around and inevitably becomes out of order).
How Can I Identify If Page Splits Are the Problem?
There are a couple of counters in Perfmon that can help, namely SQLServer:Access Methods\Page Splits/sec and SQLServer:SQL Statistics\Batch Requests/sec. Both of these should be run at the same time, as the latter metric is a helpful baseline for the former; the number of page splits per second should not exceed 20% of the number of batch requests per second.
Other factors that need to be considered include workload, workload type, table size, and fill factor for the affected index(es). For example, workloads that are heavy in INSERT and UPDATE statements are much more likely to cause page splits, and larger tables will naturally have more page splits since more data pages need to be changed. Finally, indexes with a default fill factor of 100 do not have enough free space for changes when they fill up, so page splits will naturally occur.
How Can I Fix Page Splits?
The easiest way to fix page splits is to set a fill factor value (for instance, 90) when the offending index is rebuilt. If a fill factor is not set, SQL Server uses the server-level default, which is 100 (this default can be changed, however).
What is a good value for fill factor? It depends, among other things, on the types of workloads that are regularly run, the type of environment itself, and the client’s unique needs. If the fill factor is set too high, page splits can occur, but if the fill factor is set too low, SQL Server will create new data pages more often, which can lead to wasted storage, especially on larger databases, and can lead to performance issues as well. The key is finding the right balance, which can take a lot of trial and error. However, the performance benefit will definitely be worth it.