I have a SQL Server table that contains over 20 billion rows, with 13 billion rows in the last partition.
The table is currently partitioned 6 ways by a "Time" field:
2011
2012
2013
2014
2015
2016/2017/2018
The 2016/2017/2018 partition needs to be split into their own partitions so there is a 2016, 2017, 2018 partition.
How can this be done and in the process avoiding a massive log file growth? The database is in Simple Recovery and currently each partition is in a separate file group on its own set of disks.
CREATE TABLE [dbo].[Log](
[RefNo] [nchar](7) NOT NULL,
[DevID] [nvarchar](7) NOT NULL,
[Time] [datetime] NOT NULL,
[summary] [float] NULL,
[staging] [float] NULL,
[position] [float] NULL,
CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED
(
[RefNo] ASC,
[DevID] ASC,
[Time] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 96)
)
Best Answer
Below is an example script to create the new yearly partitions. You may need to tweak the script for your actual partition function name and new filegroup names. This method assumes the operation is performed in a maintenance window when there are no inserts into the table and data for 2016 and later isn't needed for queries.
The summary of the steps performed by the script are:
There are a couple of issues with your existing table partitioning you should be aware of. Because of the
RANGE LEFT
function, datetime values that are exactly midnight on the first of the year will be placed in the wrong partition. For example, a row withTime
value '2012-01-01T00:00:00' will be in partition 1 along with year 2011 data instead of partition 2 with the rest of year 2012 data as desired. This might not be a concern unless you purge data by partition.Be mindful that the last partition if a
RANGE LEFT
function can never be removed. The implication is that the filegroup of the last partition is permanently part of the partition schemes that use the function. In your case, filegroupYear6FileGroup
will always be the last filegroup of thepsYearlyPartition_Log
scheme, although it can also be used for another partition, such as for year 2016 here.The partitions after the script is run will be as below and it is expected the last partition will be empty (assuming you have no future year data). You should create the partition for next year before the start of the year to avoid splitting a non-empty partition or avoid jumping through these hoops again.
I generally recommend a
RANGE RIGHT
function when partitioning on incremental values like datetime because the behavior is more intuitive. See Table Partitioning Best Practices for this and other considerations.