Esta semana um cliente solicitou que o particionamento atual dele com apenas um filegroup com range ate 2019-12-31 00:00:00.000 fosse modificado para o particionamento por ano, abaixo seguem os passos usados para atendar esta solicitação.
Cenário atual encontrado.
SELECT distinct * FROM (
SELECT SCHEMA_NAME(o.schema_id) + '.' + OBJECT_NAME(i.object_id) AS [object]
, p.partition_number AS [p#]
, fg.name AS [filegroup]
, p.rows
, CASE boundary_value_on_right
WHEN 1 THEN 'Less than'
ELSE 'less than or equal to' END as comparison
, rv.value
FROM sys.partitions p
INNER JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
INNER JOIN sys.objects o
ON p.object_id = o.object_id
INNER JOIN sys.system_internals_allocation_units au
ON p.partition_id = au.container_id
INNER JOIN sys.partition_schemes ps
ON ps.data_space_id = i.data_space_id
INNER JOIN sys.partition_functions f
ON f.function_id = ps.function_id
INNER JOIN sys.destination_data_spaces dds
ON dds.partition_scheme_id = ps.data_space_id
AND dds.destination_id = p.partition_number
INNER JOIN sys.filegroups fg
ON dds.data_space_id = fg.data_space_id
LEFT OUTER JOIN sys.partition_range_values rv
ON f.function_id = rv.function_id
AND p.partition_number = rv.boundary_id
WHERE i.index_id < 2
) AS T WHERE T.object LIKE '%Partitioned_Table%'
SQLModificando o particionamento para o período solicitado de 2016 ate 2027.
use db_01
go
alter database db_01 add filegroup FG_2016
alter database db_01 add filegroup FG_2017
alter database db_01 add filegroup FG_2018
alter database db_01 add filegroup FG_2019
alter database db_01 add filegroup FG_2020
alter database db_01 add filegroup FG_2021
alter database db_01 add filegroup FG_2022
alter database db_01 add filegroup FG_2023
alter database db_01 add filegroup FG_2024
alter database db_01 add filegroup FG_2025
alter database db_01 add filegroup FG_2026
alter database db_01 add filegroup FG_2027
alter database db_01
add file (
name='Reserva_FG_2016',
filename='D:\apagar\db_01_FG_2016.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2016]
alter database db_01
add file (
name='Reserva_FG_2017',
filename='D:\apagar\db_01_FG_2017.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2017]
alter database db_01
add file (
name='Reserva_FG_2018',
filename='D:\apagar\db_01_FG_2018.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2018]
alter database db_01
add file (
name='Reserva_FG_2019',
filename='D:\apagar\db_01_FG_2019.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2019]
alter database db_01
add file (
name='Reserva_FG_2020',
filename='D:\apagar\db_01_FG_2020.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2020]
alter database db_01
add file (
name='Reserva_FG_2021',
filename='D:\apagar\db_01_FG_2021.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2021]
alter database db_01
add file (
name='Reserva_FG_2022',
filename='D:\apagar\db_01_FG_2022.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2022]
alter database db_01
add file (
name='Reserva_FG_2023',
filename='D:\apagar\db_01_FG_2023.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2023]
alter database db_01
add file (
name='Reserva_FG_2024',
filename='D:\apagar\db_01_FG_2024.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2024]
alter database db_01
add file (
name='Reserva_FG_2025',
filename='D:\apagar\db_01_FG_2025.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2025]
alter database db_01
add file (
name='Reserva_FG_2026',
filename='D:\apagar\db_01_FG_2026.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2026]
alter database db_01
add file (
name='Reserva_FG_2027',
filename='D:\apagar\db_01_FG_2027.ndf',
size=128Mb,
MAXSIZE = UNLIMITED,
filegrowth=512MB
)to filegroup [FG_2027]
SQLO segredo esta aqui, iremos fazer o merge dos dados e em seguida movimentar os dados por ano sem necessidare de modificar a função ou schema atual do particionamento existente.
SELECT s.[name] AS [schema_name]
, t.[name] AS [table_name]
, i.[name] AS [index_name]
, p.[partition_number] AS [partition_number]
, SUM(a.[used_pages]*8.0) AS [partition_size_kb]
, SUM(a.[used_pages]*8.0)/1024 AS [partition_size_mb]
, CONVERT(bigint,SUM(a.[used_pages]*8.0)/1048576) AS [partition_size_gb]
, p.[rows] AS [partition_row_count]
, rv.[value] AS [partition_boundary_value] -- COLUNA USADA PARA O MERGE
, p.[data_compression_desc] AS [partition_compression_desc]
,ps.name AS PartitionSchemeName
,ds.name AS PartitionFilegroupName
,pf.name AS PartitionFunctionName
FROM sys.schemas s
JOIN sys.tables t ON t.[schema_id] = s.[schema_id]
JOIN sys.partitions p ON p.[object_id] = t.[object_id]
JOIN sys.allocation_units a ON a.[container_id] = p.[partition_id]
JOIN sys.indexes i ON i.[object_id] = p.[object_id]
AND i.[index_id] = p.[index_id]
JOIN sys.data_spaces ds ON ds.[data_space_id] = i.[data_space_id]
LEFT JOIN sys.partition_schemes ps ON ps.[data_space_id] = ds.[data_space_id]
LEFT JOIN sys.partition_functions pf ON pf.[function_id] = ps.[function_id]
LEFT JOIN sys.partition_range_values rv ON rv.[function_id] = pf.[function_id]
AND rv.[boundary_id] = p.[partition_number]
WHERE p.[index_id] <=1
AND t.[name] IN ('Partitioned_Table')
GROUP BY s.[name]
, t.[name]
, i.[name]
, p.[partition_number]
, p.[rows]
, rv.[value]
, p.[data_compression_desc]
,ps.name
,ds.name
,pf.name
order by partition_size_gb desc
SQLRealizando o merge e movimentação por ano.
use db_01
go
-- ###################### 2016 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2016];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2016-01-01T00:00:00.000');
GO
-- ###################### 2017 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2017];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2017-01-01T00:00:00.000');
GO
-- ###################### 2018 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2018];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2018-01-01T00:00:00.000');
GO
-- ###################### 2019 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2019];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2019-01-01T00:00:00.000');
GO
-- ###################### 2020 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2020];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2020-01-01T00:00:00.000');
GO
-- ###################### 2021 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2021];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2021-01-01T00:00:00.000');
GO
-- ###################### 2022 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2022];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2022-01-01T00:00:00.000');
GO
-- ###################### 2023 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2023];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2023-01-01T00:00:00.000');
GO
-- ###################### 2024 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2024];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2024-01-01T00:00:00.000');
GO
-- ###################### 2025 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2025];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2025-01-01T00:00:00.000');
GO
-- ###################### 2026 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2026];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2026-01-01T00:00:00.000');
GO
-- ###################### 2027 ######################
ALTER PARTITION SCHEME spt_rsv_atg_ecommerce_order_info NEXT USED [FG_2027];
ALTER PARTITION FUNCTION fpt_rsv_atg_ecommerce_order_info()
SPLIT RANGE(N'2027-01-01T00:00:00.000');
GO
SQLResultado final das mudanças nos particionamentos.
SELECT
OBJECT_NAME(P.object_id) AS ObjectName
, P.partition_number AS PartitionNumber
, FG.name AS FGName
, P.rows AS [Rows]
, (f.size * 8) / 1024 AS SizeMB
, AU.used_pages AS UsedPages
, F.filename AS [FileName]
, P.data_compression_desc AS [Compression]
, AU.type_desc AS TypeDesc
, S.name AS PartitionSchemeName
, PF.name AS PartitionFunctionName
, PF.boundary_value_on_right AS IsRightBoundary
, R.value AS BoundaryValue
FROM
sys.tables AS T
INNER JOIN sys.indexes AS i
ON T.object_id = I.object_id
INNER JOIN sys.partitions AS P
ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.system_internals_allocation_units AS AU
ON P.partition_id = AU.container_id
INNER JOIN sys.filegroups AS FG
ON AU.filegroup_id = FG.data_space_id
INNER JOIN sys.sysfiles AS F
ON FG.data_space_id = F.groupid
INNER JOIN sys.partition_schemes AS S
ON I.data_space_id = S.data_space_id
INNER JOIN sys.partition_functions AS PF
ON S.function_id = PF.function_id
LEFT JOIN sys.partition_range_values AS R
ON PF.function_id = R.function_id
and R.boundary_id = P.partition_number
WHERE
P.object_id = object_id('Partitioned_Table')
AND I.type <= 1
;
SQL