Published on

February 21, 2018

Compreendendo a operação SWITCH na Particionamento do SQL Server

O particionamento é um recurso poderoso no SQL Server que permite dividir tabelas grandes em partes menores e mais gerenciáveis. Uma das operações mais úteis ao trabalhar com particionamento é a operação SWITCH. Essa operação permite mover uma grande quantidade de dados de uma tabela para outra como uma operação somente de metadados, o que pode ser incrivelmente eficiente.

Uma das coisas interessantes sobre a operação SWITCH é que você pode alternar dados para uma tabela não particionada. Isso pode facilitar um pouco a sua vida, pois você não precisa gerenciar dois conjuntos de partições. No entanto, há um pequeno problema ao fazer isso, que exploraremos neste artigo.

Vamos começar criando uma tabela particionada em um banco de dados:


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

Agora, vamos inserir alguns dados de teste em nossa tabela 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 os dados e partições executando a seguinte 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;

Agora, vamos criar uma tabela não particionada que usaremos para a operação 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

Agora, vamos realizar a operação SWITCH para mover uma das partições para a tabela de alternância:


ALTER TABLE [dbo].PartitionedTable
SWITCH PARTITION 3
TO [dbo].PartitionedTable_Switch;
GO

Neste ponto, tudo funciona como esperado. No entanto, o que acontece se precisarmos alternar os dados de volta para a tabela original?


ALTER TABLE [dbo].PartitionedTable_Switch
    SWITCH 
TO [dbo].PartitionedTable
    PARTITION 3;
GO

Uh-oh! Encontramos uma mensagem de erro: “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’.”

Então, o que aconteceu? O problema é que estamos tentando inserir dados em uma partição que possui restrições. A partição tem um limite inferior de ‘2012-01-01’ e um limite superior de ‘2013-01-01’. Isso significa que nenhum dado pode entrar nessa partição que tenha valores no campo CreatedDate que não sejam maiores ou iguais a ‘2012-01-01’ e menores que ‘2013-01-01’. No entanto, nossa tabela de alternância não possui essas restrições.

Para resolver esse problema, precisamos informar ao SQL Server que os dados na tabela de alternância se encaixarão na partição. Podemos fazer isso removendo uma restrição da tabela:


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

Agora, vamos tentar a operação de alternância novamente:


ALTER TABLE [dbo].PartitionedTable_Switch
    SWITCH 
TO [dbo].PartitionedTable
    PARTITION 3;
GO

Ótimo! Os dados foram alternados com sucesso de volta para nossa tabela principal.

Portanto, embora você não precise particionar tabelas para as quais deseja alternar dados, é importante estar ciente de que, se o fizer, você precisará ser capaz de alternar esses dados de volta caso encontre algum problema. Ao entender as restrições e gerenciá-las corretamente, você pode tornar a operação SWITCH uma ferramenta poderosa em sua estratégia de particionamento do SQL Server.

Obrigado por ler!

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.