I have a table partitioned by a date column, and each partition stores one month of data.
Furthermore, each partition is associated with one filegroup, and each filegroup has exactly one db file (NDF).
My setup is pretty simple:
CREATE PARTITION FUNCTION MyPF (DATE)
AS RANGE RIGHT FOR VALUES (
'2019-09-01',
'2019-10-01',
'2019-11-01',
'2019-12-01');
CREATE PARTITION SCHEME MyPS PARTITION MyPF
TO (
FG_2019_08,
FG_2019_09,
FG_2019_10,
FG_2019_11);
I need to truncate a random month on a regular basis (sometimes even from the middle, without touching other months).
Instead of doing complicated switch out, I figured out from BOL, that TRUNCATE TABLE has WITH option in my SQL Server 2017, so I can just say:
TRUNCATE TABLE MyTable WITH (PARTITIONS(3));
TRUNCATE TABLE MyTable WITH (PARTITIONS(1));
which will remove all rows from partition from the files associated with FG_2019_08 and FG_2019_10.
That works great, and now I have an empty file, but SQL Server doesn't allow to drop: It says it still in use. My understanding, that I still need to adjust the partition function and partition schema , in order to remove the empty NDF files.
I checked out BOL, but I cannot wrap my head around how to alter (merge?) the boundary values, to reflect the changes above. They should become something like this, right?:
ALTER PARTITION FUNCTION MyPF (DATE)
AS RANGE RIGHT FOR VALUES (
'2019-10-01',
'2019-12-01');
ALTER PARTITION SCHEME MyPS PARTITION MyPF
TO (
FG_2019_09,
FG_2019_11);
Could anybody tell how could I alter these two object, if I need to alter at all?
It's easy to get confused about which filegroups things are on. Stepping back I wouldn't drop files or filegroups. I wouldn't really have filegroups at all, normally. Just create your partition scheme mapping all the partitions to a single filegroup, unless you have a really good reason not to.
Anyway here's a demo of truncating a partition and removing its file and filegroup.
use master
go
drop database parttest
go
create database partTest
go
use partTest
go
alter database current add filegroup FG_2019_08
alter database current add filegroup FG_2019_09
alter database current add filegroup FG_2019_10
alter database current add filegroup FG_2019_11
ALTER DATABASE current
ADD FILE
(
NAME = FG_2019_08,
FILENAME = 'C:\temp\partTest_FG_2019_08.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP FG_2019_08;
ALTER DATABASE current
ADD FILE
(
NAME = FG_2019_09,
FILENAME = 'C:\temp\partTest_FG_2019_09.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP FG_2019_09;
ALTER DATABASE current
ADD FILE
(
NAME = FG_2019_10,
FILENAME = 'C:\temp\partTest_FG_2019_10.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP FG_2019_10;
ALTER DATABASE current
ADD FILE
(
NAME = FG_2019_11,
FILENAME = 'C:\temp\partTest_FG_2019_11.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP FG_2019_11;
CREATE PARTITION FUNCTION MyPF (DATE)
AS RANGE RIGHT FOR VALUES (
'2019-09-01',
'2019-10-01',
'2019-11-01'
);
CREATE PARTITION SCHEME MyPS AS PARTITION MyPF
TO (
FG_2019_08,
FG_2019_09,
FG_2019_10,
FG_2019_11
);
go
create table p ( d date ) on MyPs(d)
insert into p(d) values ('20190801'),('20190901'),('20191001'),('20191101')
declare @p int = $partition.MyPf('20190801')
TRUNCATE TABLE p WITH (PARTITIONS(@p));
set @p = $partition.MyPf('20191001')
TRUNCATE TABLE p WITH (PARTITIONS(@p));
alter partition function MyPF() merge range ('20190901')
alter database current remove file FG_2019_09
alter database current remove filegroup FG_2019_09