Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Criar uma tabela particionada no SQL Server (T-SQL)


O SQL Server oferece suporte a tabelas e índices particionados. Quando uma tabela ou índice particionado é particionado, seus dados são divididos em unidades que podem ser distribuídas por mais de um grupo de arquivos.

Portanto, para criar uma tabela particionada no SQL Server, primeiro você precisa criar os grupos de arquivos que conterão cada partição. Você também precisa criar uma função de partição e um esquema de partição.

Então fica assim:
  1. Criar grupos de arquivos
  2. Criar uma função de partição
  3. Criar um esquema de partição
  4. Crie a tabela particionada

Abaixo está um exemplo de como usar essas etapas para criar uma tabela com quatro partições.

Criar grupos de arquivos


Primeiro, adicionamos quatro grupos de arquivos ao banco de dados chamado Test e especifique o arquivo físico para cada um desses grupos de arquivos.
ALTER DATABASE Test
ADD FILEGROUP MoviesFg1;
GO  
ALTER DATABASE Test  
ADD FILEGROUP MoviesFg2;  
GO  
ALTER DATABASE Test  
ADD FILEGROUP MoviesFg3;  
GO  
ALTER DATABASE Test  
ADD FILEGROUP MoviesFg4;   

ALTER DATABASE Test   
ADD FILE   
(  
    NAME = MoviesFg1dat,  
    FILENAME = '/var/opt/mssql/data/MoviesFg1dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB  
)  
TO FILEGROUP MoviesFg1;  
ALTER DATABASE Test   
ADD FILE   
(  
    NAME = MoviesFg2dat,  
    FILENAME = '/var/opt/mssql/data/MoviesFg2dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB  
)  
TO FILEGROUP MoviesFg2;  
GO  
ALTER DATABASE Test   
ADD FILE   
(  
    NAME = MoviesFg3dat,  
    FILENAME = '/var/opt/mssql/data/MoviesFg3dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB  
)  
TO FILEGROUP MoviesFg3;  
GO  
ALTER DATABASE Test   
ADD FILE   
(  
    NAME = MoviesFg4dat,  
    FILENAME = '/var/opt/mssql/data/MoviesFg4dat.ndf',  
    SIZE = 5MB,  
    MAXSIZE = 100MB,  
    FILEGROWTH = 5MB  
)  
TO FILEGROUP MoviesFg4;  
GO  

Você precisará alterar esse código, dependendo de seus requisitos. Você também precisará alterar os caminhos de arquivo para se adequar ao seu ambiente. Por exemplo, se você estiver no Windows, seu caminho pode se parecer mais com D:\mssql\data\MoviesFg4dat.ndf .

Além disso, se você precisar de mais partições, adicione mais grupos de arquivos aqui. Por outro lado, se você precisar de menos partições, especifique menos grupos de arquivos aqui.

Criar uma função de partição


Em seguida, criamos uma função de partição chamada MoviesPartitionFunction que irá particionar a tabela em quatro partições.
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
    AS RANGE LEFT FOR VALUES (1, 100, 1000);
GO

O int parte especifica o tipo de dados da coluna usada para particionamento.

Todos os tipos de dados são válidos para uso como colunas de particionamento, exceto texto , ntext , imagem , xml , carimbo de data e hora , varchar(max) , nvarchar(max) , varbinary(max) , tipos de dados de alias ou tipos de dados CLR definidos pelo usuário.

Aqui, eu uso três valores de limite (1, 100 e 1000 ) para especificar quatro partições. Esses valores de limite devem corresponder ou ser implicitamente conversíveis para o tipo de dados especificado entre parênteses após o nome da função de partição.

Dados esses valores de limite e o fato de eu especificar um RANGE LEFT partição, as quatro partições manterão os valores especificados na tabela a seguir.
Partição Valores
1 <= 1
2 1 E <= 100
3 100 E <=1000
4 1000

Se eu tivesse especificado um RANGE RIGHT partição, a divisão seria um pouco diferente, conforme descrito na tabela a seguir.
Partição Valores
1 1
2 >= 1 E < 100
3 >= 100 E < 1000
4 >= 1000

O mesmo conceito se aplica se a coluna de particionamento usar outros tipos de dados, como valores de data/hora.

Criar um esquema de partição


Em seguida, precisamos criar um esquema de partição.

Um esquema de partição mapeia as partições de uma tabela ou índice particionado para os novos grupos de arquivos.

No nosso caso, o código ficará assim:
CREATE PARTITION SCHEME MoviesPartitionScheme  
    AS PARTITION MoviesPartitionFunction  
    TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);  
GO

Observe que fazemos referência à função de partição que criamos na etapa anterior. Também referenciamos os grupos de arquivos que criamos na primeira etapa.

Criar a tabela particionada


Finalmente, podemos criar a tabela particionada.
CREATE TABLE Movies (
    MovieId int IDENTITY PRIMARY KEY, 
    MovieName varchar(60)
    )  
    ON MoviesPartitionScheme (MovieId);  
GO

A única diferença entre isso e criar uma tabela não particionada é que ao criar uma tabela particionada, usamos o ON argumento para especificar um esquema de partição a ser usado. No nosso caso, especificamos o esquema de partição que criamos na etapa anterior e especificamos o MovieId coluna como a coluna de particionamento.

Você notará que o MovieId coluna tem um tipo de dados de int , que corresponde aos valores de limite que especificamos ao criar a função de partição.

Observe que, se você usar uma coluna computada em uma função de partição, ela deverá ser marcada explicitamente como PERSISTED .

Verifique a função de partição


Você pode usar as sys.partition_functions view para retornar todas as funções de partição.
SELECT * FROM sys.partition_functions;

Resultado (usando saída vertical):
name                    | MoviesPartitionFunction
function_id             | 65536
type                    | R 
type_desc               | RANGE
fanout                  | 4
boundary_value_on_right | 0
is_system               | 0
create_date             | 2020-10-10 05:37:41.330
modify_date             | 2020-10-10 05:37:41.330

Verifique o esquema de partição


Você pode usar sys.partition_schemes para verificar o esquema de partição.
SELECT * FROM sys.partition_schemes;

Resultado (usando saída vertical):
name          | MoviesPartitionScheme
data_space_id | 65601
type          | PS
type_desc     | PARTITION_SCHEME
is_default    | 0
is_system     | 0
function_id   | 65536

Como alternativa, você pode usar a consulta a seguir para retornar outros detalhes, como esquema, tabela, índice etc.
SELECT 
    object_schema_name(i.object_id) AS [Schema],
    object_name(i.object_id) AS [Object],
    i.name AS [Index],
    s.name AS [Partition Scheme]
    FROM sys.indexes i
    INNER JOIN sys.partition_schemes s ON i.data_space_id = s.data_space_id;

Resultado (usando saída vertical):
Schema           | dbo
Object           | Movies
Index            | PK__Movies__4BD2941A0ED85ACA
Partition Scheme | MoviesPartitionScheme

Verifique a tabela particionada


Você pode executar o sys.dm_db_partition_stats view para retornar informações de página e contagem de linhas para cada partição no banco de dados atual.

Mas executar isso antes de inserir qualquer dado na tabela fará com que a maioria das estatísticas seja zero.

Então eu vou inserir os dados primeiro.
INSERT INTO Movies
SELECT name FROM OtherDb.dbo.Movies;

Resultado:
(4079 rows affected)

Podemos ver que foram inseridas 4.079 linhas.

Agora vamos consultar o sys.dm_db_partition_stats visualizar.
SELECT *
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Resultado:
+-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+
| partition_id      | object_id   | index_id   | partition_number   | in_row_data_page_count   | in_row_used_page_count   | in_row_reserved_page_count   | lob_used_page_count   | lob_reserved_page_count   | row_overflow_used_page_count   | row_overflow_reserved_page_count   | used_page_count   | reserved_page_count   | row_count   |
|-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------|
| 72057594048413696 | 2030630277  | 1          | 1                  | 1                        | 2                        | 9                            | 0                     | 0                         | 0                              | 0                                  | 2                 | 9                     | 1           |
| 72057594048479232 | 2030630277  | 1          | 2                  | 1                        | 2                        | 9                            | 0                     | 0                         | 0                              | 0                                  | 2                 | 9                     | 99          |
| 72057594048544768 | 2030630277  | 1          | 3                  | 3                        | 5                        | 25                           | 0                     | 0                         | 0                              | 0                                  | 5                 | 25                    | 900         |
| 72057594048610304 | 2030630277  | 1          | 4                  | 10                       | 12                       | 33                           | 0                     | 0                         | 0                              | 0                                  | 12                | 33                    | 3079        |
+-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+

Essa visualização retorna muitas colunas, então vamos restringir as colunas a apenas algumas.
SELECT 
    partition_number,
    row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Resultado:
+--------------------+-------------+
| partition_number   | row_count   |
|--------------------+-------------|
| 1                  | 1           |
| 2                  | 99          |
| 3                  | 900         |
| 4                  | 3079        |
+--------------------+-------------+

Podemos ver como as linhas são alocadas nas partições. Eles são alocados exatamente como especificamos na função de partição. As linhas totalizam 4.079, que é exatamente quantas linhas inserimos.

No entanto, vale a pena notar que a documentação da Microsoft realmente afirma que esta coluna é apenas um aproximado contagem das linhas em cada partição.

Prática recomendada


A Microsoft recomenda que sempre mantenhamos partições vazias em ambas as extremidades do intervalo de partição.

Isso é no caso de você precisar dividir ou mesclar as partições no futuro.

O motivo dessa recomendação é garantir que a divisão da partição e a mesclagem da partição não incorram em nenhuma movimentação inesperada de dados.

Portanto, dados os dados no meu exemplo, eu poderia alterar a função de partição para algo assim:
CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
    AS RANGE LEFT FOR VALUES (-1, 100, 10000);
GO

Ou se eu antecipar mais de 10.000 linhas, posso usar um número maior (ou criar mais partições).

Se eu recriasse todas as etapas novamente, para criar minha tabela particionada, minhas estatísticas de partição ficariam assim:
SELECT 
    partition_number,
    row_count
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('dbo.Movies');

Resultado:
+--------------------+-------------+
| partition_number   | row_count   |
|--------------------+-------------|
| 1                  | 0           |
| 2                  | 100         |
| 3                  | 3979        |
| 4                  | 0           |
+--------------------+-------------+

Agora meus dados estão concentrados nas duas partições do meio e as partições nas duas extremidades estão vazias.