Оператор ALTER TABLE SWITCH не выполнен.Диапазон, определенный разделом 1 в таблице X, не является подмножеством диапазона, определенного разделом 2 в таблице Y - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь создать простую процедуру замены разделов в Azure SQL DataWarehouse на основе раздела «Оптимизация с переключением разделов» здесь https://docs.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-best-practices-transactions

Я думаю, что у меня есть раздел, который я пытаюсь поменятьвыровнен, но получаю сообщение об ошибке, которое, как мне кажется, говорит о том, что это не так (оператор ALTER TABLE SWITCH не выполнен. Диапазон, определенный разделом 1 в таблице 'Distribution_55.dbo.Table_42b5ce68198a4fe1a2c5a597075b93d5_55', не является подмножеством диапазона, определенного разделом 2 в таблице'Distribution_55.dbo.Table_62915da3af53441980fedba6da729c62_55')

Вот мое полное повторение:

--Create a view for us to use to look up the partition numbers later
CREATE VIEW dbo.TablePartitions
AS
    SELECT
        s.name SchemaName
        ,t.name TableName
        ,CAST(r.value as nvarchar(128)) BoundaryValue
        ,p.partition_number PartitionNumber
    FROM        
        sys.schemas s
        JOIN sys.tables t
            ON s.[schema_id] = t.[schema_id]
        JOIN sys.indexes i
            ON t.[object_id] = i.[object_id]
        JOIN sys.partitions p 
            ON i.[object_id] = p.[object_id] 
            AND i.[index_id] = p.[index_id] 
        JOIN sys.partition_schemes h 
            ON i.[data_space_id] = h.[data_space_id]
        JOIN sys.partition_functions f
            ON h.[function_id] = f.[function_id]
        LEFT JOIN sys.partition_range_values r
            ON f.[function_id] = r.[function_id] 
            AND r.[boundary_id] = p.[partition_number]
    WHERE 
        i.[index_id] <= 1;

--Create our main partitioned table
CREATE TABLE [dbo].[PartitionedTable](
    [DistributionField] [nvarchar](30) NOT NULL,
    [PartitionField] [int] NOT NULL,
    [Value] [int] NOT NULL
)
WITH (
    DISTRIBUTION = HASH( [DistributionField] ),
    PARTITION ( [PartitionField] RANGE RIGHT FOR VALUES() ),
    CLUSTERED COLUMNSTORE INDEX
)

--Create the main table's partition boundaries
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (1)
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (2)
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (3)

--Create a staging table for partition swapping
CREATE TABLE [dbo].[PartitionedTableStaging]
WITH
(    
    DISTRIBUTION = HASH( [DistributionField] ),
    PARTITION ( [PartitionField] RANGE RIGHT FOR VALUES() ),
    CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT *
FROM    [dbo].[PartitionedTable]
WHERE 1=2

--Create boundaries that will align the partition that PartitionValue = 2 will fall into
ALTER TABLE dbo.[PartitionedTableStaging] SPLIT RANGE (2)
ALTER TABLE dbo.[PartitionedTableStaging] SPLIT RANGE (3)

--Load the staging table with values where PartitionValue = 2
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('X', 2, 1)
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('Y', 2, 2)
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('Z', 2, 3)

--Find the partition numbers that we will swap
select * from TablePartitions where SchemaName = 'dbo' and TableName = 'PartitionedTable' and BoundaryValue = 2
select * from TablePartitions where SchemaName = 'dbo' and TableName = 'PartitionedTableStaging' and BoundaryValue = 2

--Swap the staged partition over to the main table
ALTER TABLE PartitionedTableStaging SWITCH PARTITION 1 TO PartitionedTable PARTITION 2;

Не являются ли границы для разделов, в которых PartitionField = 2 выровнены?

1 Ответ

0 голосов
/ 15 февраля 2019

Оказывается, я неправильно понял, как работают RANGE RIGHT и RANGE LEFT.Например, RANGE RIGHT помещает значение (2 является значением, на котором сфокусировано репро) в раздел 3 вместо раздела 2. Если вы измените репро, чтобы использовать RANGE LEFT, и создайте нижнюю границу для раздела 2 в промежуточной таблице (создав границу для значения 1), затем раздел 2 на промежуточной и рабочей таблицах выровняется, и своп работает.Вот исправленный образец:

--Create a view for us to use to look up the partition numbers later
CREATE VIEW dbo.TablePartitions
AS
    SELECT
        s.name SchemaName
        ,t.name TableName
        ,CAST(r.value as nvarchar(128)) BoundaryValue
        ,p.partition_number PartitionNumber
    FROM        
        sys.schemas s
        JOIN sys.tables t
            ON s.[schema_id] = t.[schema_id]
        JOIN sys.indexes i
            ON t.[object_id] = i.[object_id]
        JOIN sys.partitions p 
            ON i.[object_id] = p.[object_id] 
            AND i.[index_id] = p.[index_id] 
        JOIN sys.partition_schemes h 
            ON i.[data_space_id] = h.[data_space_id]
        JOIN sys.partition_functions f
            ON h.[function_id] = f.[function_id]
        LEFT JOIN sys.partition_range_values r
            ON f.[function_id] = r.[function_id] 
            AND r.[boundary_id] = p.[partition_number]
    WHERE 
        i.[index_id] <= 1;

--Create our main partitioned table
CREATE TABLE [dbo].[PartitionedTable](
    [DistributionField] [nvarchar](30) NOT NULL,
    [PartitionField] [int] NOT NULL,
    [Value] [int] NOT NULL
)
WITH (
    DISTRIBUTION = HASH( [DistributionField] ),
    PARTITION ( [PartitionField] RANGE LEFT FOR VALUES() ),
    CLUSTERED COLUMNSTORE INDEX
)

--Create the main table's partition boundaries
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (1)
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (2)
ALTER TABLE dbo.[PartitionedTable] SPLIT RANGE (3)

--Create a staging table for partition swapping
CREATE TABLE [dbo].[PartitionedTableStaging]
WITH
(    
    DISTRIBUTION = HASH( [DistributionField] ),
    PARTITION ( [PartitionField] RANGE LEFT FOR VALUES() ),
    CLUSTERED COLUMNSTORE INDEX
)
AS
SELECT *
FROM    [dbo].[PartitionedTable]
WHERE 1=2

--Create boundaries that will align the partition that PartitionValue = 2 will fall into
ALTER TABLE dbo.[PartitionedTableStaging] SPLIT RANGE (1)
ALTER TABLE dbo.[PartitionedTableStaging] SPLIT RANGE (2)

--Load the staging table with values where PartitionValue = 2
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('X', 2, 1)
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('Y', 2, 2)
INSERT INTO PartitionedTableStaging (DistributionField, PartitionField, Value) VALUES ('Z', 2, 3)

--Find the partition numbers that we will swap
select * from TablePartitions where SchemaName = 'dbo' and TableName = 'PartitionedTable' and BoundaryValue = 2
select * from TablePartitions where SchemaName = 'dbo' and TableName = 'PartitionedTableStaging' and BoundaryValue = 2

--Swap the staged partition over to the main table
ALTER TABLE PartitionedTableStaging SWITCH PARTITION 2 TO PartitionedTable PARTITION 2;
...