在Create Index时,必须慎重考虑属性FillFactor 和 PAD_INDEX的设置,这两个属性只在create index 或 rebuild index时起作用,表示Index page(Leaf-Level 或 intermediate-Level)的填充程度。如果设置FillFactor=90,那么SQL Server 在create index 或 rebuild index时,不是将Index Page的空间全部用完,而是只使用接近90%的Page空间,预留10%的空闲空间,这预留的Page内部的空间叫做 Internal Fragmentation。预留一定比例的Fragmentation有一定的用途,reduce page split,能够提高数据更新的性能;而Fragmentation 太多,会降低查询性能。
Index 是BTree 结构,分为Leaf-Level Page 和 Intermediate-Level Page(即NonLeaf-Level Page)。
FillFactor 属性指定Index Leaf-Level pages的填充percent,MS建议FillFactor=90。
PAD_INDEX 属性是boolean 类型,指定是否使用FillFactor 来填充Index Intermediate-Level Pages。
An explicit FILLFACTOR setting applies only when the index is first created or rebuilt. 在插入数据时,SQL Server 尽可能使用Page全部的空间,而不会考虑填充属性。
1,PAD_INDEX = { ON | OFF }
Specifies index padding. The default is OFF.
- ON The percentage of free space that is specified by fillfactor is applied to the intermediate-level pages of the index.
- OFF or fillfactor is not specified
-
The intermediate-level pages are filled to near capacity, leaving sufficient space for at least one row of the maximum size the index can have, considering the set of keys on the intermediate pages.
The PAD_INDEX option is useful only when FILLFACTOR is specified, because PAD_INDEX uses the percentage specified by FILLFACTOR. If the percentage specified for FILLFACTOR is not large enough to allow for one row, the Database Engine internally overrides the percentage to allow for the minimum. The number of rows on an intermediate index page is never less than two, regardless of how low the value of fillfactor.
2,FILLFACTOR =fillfactor
Specifies a percentage that indicates how full the Database Engine should make the leaf level of each index page during index creation or rebuild. fillfactor must be an integer value from 1 to 100. If fillfactor is 100, the Database Engine creates indexes with leaf pages filled to capacity.The default is 0.
An explicit FILLFACTOR setting applies only when the index is first created or rebuilt.
The FILLFACTOR setting applies only when the index is created or rebuilt. The Database Engine does not dynamically keep the specified percentage of empty space in the pages. To view the fill factor setting, use the sys.indexes catalog view.
Important |
---|
Creating a clustered index with a FILLFACTOR less than 100 affects the amount of storage space the data occupies because the Database Engine redistributes the data when it creates the clustered index. |
3,Specify Fill Factor for an index
The fill-factor option is provided for fine-tuning index data storage and performance. When an index is created or rebuilt, the fill-factor value determines the percentage of space on each leaf-level page to be filled with data, reserving the remainder on each page as free space for future growth. For example, specifying a fill-factor value of 80 means that 20 percent of each leaf-level page will be left empty, providing space for index expansion as data is added to the underlying table. The empty space is reserved between the index rows rather than at the end of the index.
The fill-factor value is a percentage from 1 to 100, and the server-wide default is 0 which means that the leaf-level pages are filled to capacity.Fill-factor values 0 and 100 are the same in all respects.
4,Performance Considerations
Page Splits
A correctly chosen fill-factor value can reduce potential page splits by providing enough space for index expansion as data is added to the underlying table.When a new row is added to a full index page, the Database Engine moves approximately half the rows to a new page to make room for the new row. This reorganization is known as a page split. A page split makes room for new records, but can take time to perform and is a resource intensive operation. Also, it can cause fragmentation that causes increased I/O operations. When frequent page splits occur, the index can be rebuilt by using a new or existing fill-factor value to redistribute the data. For more information, see Reorganize and Rebuild Indexes.
Although a low, nonzero fill-factor value may reduce the requirement to split pages as the index grows, the index will require more storage space and can decrease read performance. Even for an application oriented for many insert and update operations, the number of database reads typically outnumber database writes by a factor of 5 to 10. Therefore, specifying a fill factor other than the default can decrease database read performance by an amount inversely proportional to the fill-factor setting. For example, a fill-factor value of 50 can cause database read performance to decrease by two times. Read performance is decreased because the index contains more pages, therefore increasing the disk IO operations required to retrieve the data.
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.
5,An Example To specify a fill factor in an existing index
Script1
-- Rebuilds the IX_Employee_OrganizationLevel_OrganizationNode index -- with a fill factor of 80 on the HumanResources.Employee table. ALTER INDEX IX_Employee_OrganizationLevel_OrganizationNode ON HumanResources.Employee REBUILD WITH (FILLFACTOR = 80);
Script2
CREATE INDEX IX_Employee_OrganizationLevel_OrganizationNode ON HumanResources.Employee (OrganizationLevel, OrganizationNode) WITH (DROP_EXISTING = ON, FILLFACTOR = 80);
参考文档:
https://msdn.microsoft.com/en-us/library/ms188783(v=sql.110).aspx
https://msdn.microsoft.com/en-us/library/ms177459(v=sql.110).aspx