La partición es una característica poderosa en SQL Server que te permite dividir tablas grandes en piezas más pequeñas y manejables. Una de las operaciones más útiles al trabajar con particiones es la operación SWITCH. Esta operación te permite mover una gran cantidad de datos de una tabla a otra como una operación solo de metadatos, lo cual puede ser increíblemente eficiente.
Una de las cosas interesantes sobre la operación SWITCH es que puedes cambiar datos a una tabla no particionada. Esto puede facilitarte un poco la vida porque no tienes que administrar dos conjuntos de particiones. Sin embargo, hay un pequeño problema al hacer esto, que exploraremos en este artículo.
Comencemos creando una tabla particionada en una base de datos:
CREATE DATABASE [PartitioningDemo]
GO
USE [PartitioningDemo];
GO
CREATE PARTITION FUNCTION PF_PartitionedTable(DATE)
AS RANGE RIGHT
FOR VALUES ('2011-01-01','2012-01-01','2013-01-01',
'2014-01-01','2015-01-01','2016-01-01',
'2017-01-01');
GO
CREATE PARTITION SCHEME PS_PartitionedTable
AS PARTITION PF_PartitionedTable
ALL TO ([PRIMARY]);
GO
CREATE TABLE dbo.PartitionedTable
(ID INT IDENTITY(1,1),
ColA VARCHAR(10),
ColB VARCHAR(10),
CreatedDate DATE)
ON PS_PartitionedTable(CreatedDate);
GO
Ahora, insertemos algunos datos de prueba en nuestra tabla particionada:
SET NOCOUNT ON;
DECLARE @FromDate date = '2011-01-01';
DECLARE @ToDate date = '2017-01-01';
INSERT INTO dbo.PartitionedTable
SELECT
REPLICATE('A',10),
REPLICATE('B',10),
DATEADD(DD,FLOOR(RAND()*(DATEDIFF(DD,@FromDate,@ToDate))),@FromDate);
GO 1000
Podemos verificar los datos y las particiones ejecutando la siguiente consulta:
SELECT
p.partition_number, p.partition_id, fg.name AS [filegroup],
r.boundary_id, CONVERT(DATE,r.value) AS BoundaryValue, p.rows
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.allocation_units a ON a.container_id = p.hobt_id
INNER JOIN
sys.filegroups fg ON fg.data_space_id = a.data_space_id
INNER JOIN
sys.partition_schemes AS s ON i.data_space_id = s.data_space_id
INNER JOIN
sys.partition_functions AS f ON s.function_id = f.function_id
LEFT OUTER JOIN
sys.partition_range_values AS r ON f.function_id = r.function_id
AND r.boundary_id = p.partition_number
WHERE
i.type <= 1 AND a.type = 1
AND
t.name = 'PartitionedTable'
ORDER BY
p.partition_number
DESC;
Ahora, creemos una tabla no particionada que utilizaremos para la operación SWITCH:
USE [PartitioningDemo];
GO
CREATE TABLE dbo.PartitionedTable_Switch
(ID INT IDENTITY(1,1),
ColA VARCHAR(10),
ColB VARCHAR(10),
CreatedDate DATE)
ON [PRIMARY];
GO
Ahora, realicemos la operación SWITCH para mover una de las particiones a la tabla de cambio:
ALTER TABLE [dbo].PartitionedTable
SWITCH PARTITION 3
TO [dbo].PartitionedTable_Switch;
GO
En este punto, todo funciona como se esperaba. Sin embargo, ¿qué sucede si necesitamos cambiar los datos de vuelta a la tabla original?
ALTER TABLE [dbo].PartitionedTable_Switch
SWITCH
TO [dbo].PartitionedTable
PARTITION 3;
GO
¡Ups! Nos encontramos con un mensaje de error: “Msg 4982, Level 16, State 1, Line 4 ALTER TABLE SWITCH statement failed. Check constraints of source table ‘PartitioningDemo.dbo.PartitionedTable_Switch’ allow values that are not allowed by range defined by partition 3 on target table ‘PartitioningDemo.dbo.PartitionedTable’.”
Entonces, ¿qué sucedió? El problema es que estamos intentando insertar datos en una partición que tiene restricciones. La partición tiene un límite inferior de ‘2012-01-01’ y un límite superior de ‘2013-01-01’. Esto significa que no se puede ingresar datos en esa partición que tengan valores en el campo CreatedDate que no sean mayores o iguales a ‘2012-01-01’ y menores a ‘2013-01-01’. Sin embargo, nuestra tabla de cambio no tiene estas restricciones.
Para resolver este problema, debemos indicarle a SQL Server que los datos en la tabla de cambio se ajustarán a la partición. Podemos hacer esto eliminando una restricción en la tabla:
ALTER TABLE dbo.PartitionedTable_Switch
ADD CONSTRAINT CreatedDate_Switch_CHECK CHECK
(CreatedDate >= CONVERT(DATE,'2012-01-01') AND CreatedDate < CONVERT(DATE,'2013-01-01')
AND CreatedDate IS NOT NULL);
GO
Ahora, intentemos nuevamente la operación de cambio:
ALTER TABLE [dbo].PartitionedTable_Switch
SWITCH
TO [dbo].PartitionedTable
PARTITION 3;
GO
¡Genial! Los datos se han cambiado correctamente de vuelta a nuestra tabla principal.
Entonces, aunque no es necesario particionar las tablas a las que deseas cambiar datos, es importante tener en cuenta que si lo haces, debes poder cambiar esos datos de vuelta en caso de que encuentres algún problema. Al comprender las restricciones y administrarlas correctamente, puedes convertir la operación SWITCH en una herramienta poderosa en tu estrategia de particionamiento de SQL Server.
¡Gracias por leer!