1

取得日で分割されたテーブルがあります

テーブル構造(テーブル名:在庫)

Vendor_Name [varchar](80) NULL,
Model_Name [varchar](80) NULL,
AcquisitionDate [datetime] NOT NULL,
Qty [bigint] NOT NULL

インベントリ テーブルのパーティション関数:

CREATE PARTITION FUNCTION [Inventory_PF_New](datetime) AS RANGE LEFT FOR VALUES 
(N'2012-07-01T00:00:00.000', N'2012-08-01T00:00:00.000', 
N'2012-09-01T00:00:00.000', N'2012-10-01T00:00:00.000', 
N'2012-11-01T00:00:00.000', N'2012-12-01T00:00:00.000', 
N'2013-01-01T00:00:00.000', N'2013-02-01T00:00:00.000', 
N'2013-03-01T00:00:00.000', N'2013-04-01T00:00:00.000', 
N'2013-05-01T00:00:00.000', N'2013-06-01T00:00:00.000', 
N'2013-07-01T00:00:00.000', N'2013-08-01T00:00:00.000', 
N'2013-09-01T00:00:00.000', N'2013-10-01T00:00:00.000', 
N'2013-11-01T00:00:00.000', N'2013-12-01T00:00:00.000', 
N'2014-01-01T00:00:00.000', N'2014-02-01T00:00:00.000', 
N'2014-03-01T00:00:00.000', N'2014-04-01T00:00:00.000', 
)

最大 3 か月前の取得日を持つことができる毎日のフィード フラット ファイルを受け取ります。これらのファイルを処理し、データを実際のパーティション テーブル (インベントリ テーブル) にロードする必要があります。

Bulk Insert/SSIS を使用すると、これらのファイルを一時テーブルに簡単にロードできますが、ALTER SWITCH を使用して毎日受信したデータを実際のパーティション テーブルに切り替えるにはどうすればよいですか? 受信パーティションは空である必要があり、データを一時テーブルにロードすると、3か月分のデータが含まれる可能性があります。だから、単純に ALTER SWITCH IN を実行することはできません。

これを実装するにはどうすればよいですか。私の要件は、毎日受信したデータをすばやく読み込むことであり、私の毎日のフィードには 3 か月分のデータを含めることができますか?

私のテーブルは取得日を使用して月ごとに分割されており、3 ~ 4 か月のデータを持つデータ フィードを受け取ります。ALTER SWITCH を使用してこのデータを実際のパーティション テーブルにロードするにはどうすればよいですか?

4

2 に答える 2

0

私があなたに質問したいのは、「テーブルがパーティション化されていると確信していますか?」ということです。一般的に言えば、データを一時的な場所にステージングするかどうかに関係なく、適切にパーティション分割されたテーブルへの挿入は、パーティション関数で使用される主キーに沿ってデータを正しく配置する必要があります。

以下の例では、単純なパーティションを使用してカタログを作成し、レコードをパーティション テーブルに挿入します (パーティション テーブルにはパーティション分割された列が主キーの少なくとも一部である必要があるため、明らかにした構造に大まかに基づいています。元の例に表示されます)。提供される結果は、1 回の挿入後の予期されるファイル ( 20140101 および 20140102 ) の増加と、最終的にパーティション内のそれらの行の実際の割り当てを示しています。後者のクエリは、データが適切に割り当てられているかどうかを判断するのに役立ちます。そうでない場合は、残りの例からそれを修正する方法についての洞察を得ることができるかもしれません!

以下のコードは、以下のコメントで概説されているように、SWITCH の使用法を示すように変更されています。

テスト カタログを作成します。

USE master;
GO

-- Make a data directory;
-- EXECUTE xp_cmdshell 'mkdir D:\MSSQL\DATA\PartitionExample\';

-- Create a catalog for testing;
IF NOT EXISTS ( SELECT  1
                FROM    sys.databases
                WHERE   name = 'PartitionExample' )
BEGIN
    --DROP DATABASE [PartitionExample];
    CREATE DATABASE [PartitionExample]
    ON PRIMARY (
        NAME = [PartitionExample_dat],
        FILENAME = 'D:\MSSQL\DATA\PartitionExample\PartitionExample.mdf',
        SIZE = 3MB,
        FILEGROWTH = 1MB )
    LOG ON (
        NAME = [PartitionExample_log],
        FILENAME = 'D:\MSSQL\DATA\PartitionExample\PartitionExample.ldf',
        SIZE = 512KB, 
        FILEGROWTH = 512KB );
END;
GO

-- Add filegroups and files for partitions;
IF NOT EXISTS ( SELECT *
                FROM    PartitionExample.sys.sysfiles
                WHERE   name LIKE 'fg[_]DateRange[_]________[_]dat' )
BEGIN
    -- Filegroups
    ALTER DATABASE [PartitionExample]
    ADD FILEGROUP [fg_DateRange_20140101];

    ALTER DATABASE [PartitionExample]
    ADD FILEGROUP [fg_DateRange_20140102];

    ALTER DATABASE [PartitionExample]
    ADD FILEGROUP [fg_DateRange_20140103];

    -- Files
    ALTER DATABASE [PartitionExample]
    ADD FILE (
        NAME = [fg_DateRange_20140101_dat],
        FILENAME = 'D:\MSSQL\DATA\PartitionExample\fg_DateRange_20140101.ndf',
        SIZE = 512KB,
        FILEGROWTH = 512KB )
        TO FILEGROUP [fg_DateRange_20140101];

    ALTER DATABASE PartitionExample
    ADD FILE (
        NAME = [fg_DateRange_20140102_dat],
        FILENAME = 'D:\MSSQL\DATA\PartitionExample\fg_DateRange_20140102.ndf',
        SIZE = 512KB,
        FILEGROWTH = 512KB )
        TO FILEGROUP [fg_DateRange_20140102];

    ALTER DATABASE PartitionExample
    ADD FILE (
        NAME = [fg_DateRange_20140103_dat],
        FILENAME = 'D:\MSSQL\DATA\PartitionExample\fg_DateRange_20140103.ndf',
        SIZE = 512KB,
        FILEGROWTH = 512KB )
        TO FILEGROUP [fg_DateRange_20140103];
END;
GO

パーティション スキーム/機能の構築

-- Use the newly created catalog;
USE [PartitionExample];
GO

-- Set up partition function and scheme;
IF NOT EXISTS ( SELECT  1
                FROM    sys.partition_functions
                WHERE   name = 'pf_DateRange' )
BEGIN
    --DROP PARTITION SCHEME [ps_DateRange];
    --DROP PARTITION FUNCTION [pf_DateRange];
    CREATE PARTITION FUNCTION [pf_DateRange] ( DATETIME )
    AS RANGE RIGHT FOR VALUES ( '20140101', '20140102', '20140103' );

    CREATE PARTITION SCHEME [ps_DateRange]
    AS PARTITION [pf_DateRange] TO ( [PRIMARY], 
        [fg_DateRange_20140101], [fg_DateRange_20140102], [fg_DateRange_20140103] );
END;
GO

分割されたテーブルを作成して入力します。

-- Create table;
IF NOT EXISTS ( SELECT  1
                FROM    sys.objects
                WHERE   name = 'Inventory'
                    AND type = 'U' )
BEGIN
    --DROP TABLE dbo.Inventory;
    CREATE TABLE dbo.Inventory
    (
        Inventory_PK        INTEGER IDENTITY( 1, 1 ) NOT NULL,
        AcquisitionDate     DATETIME NOT NULL,
                                PRIMARY KEY ( Inventory_PK, AcquisitionDate ),
        Vendor_Name         VARCHAR( 80 ) NULL,
        Model_Name          VARCHAR( 80 ) NULL,
        Qty                 BIGINT NOT NULL
    ) ON ps_DateRange( AcquisitionDate );
END;
GO

-- "Stage" data, for initial population purposes
SET NOCOUNT ON;

IF NOT EXISTS ( SELECT  1
                FROM    dbo.Inventory )
BEGIN
    DECLARE @i      INTEGER;

    CREATE TABLE dbo.t_StageInventory
    (
        Inventory_PK        INTEGER IDENTITY( 1, 1 ) NOT NULL,
        AcquisitionDate     DATETIME NOT NULL,
                                PRIMARY KEY ( Inventory_PK, AcquisitionDate ),
        Vendor_Name         VARCHAR( 80 ) NULL,
        Model_Name          VARCHAR( 80 ) NULL,
        Qty                 BIGINT NOT NULL
    ) ON ps_DateRange( AcquisitionDate );

        SET @i = 0;
    WHILE ( @i < 100 )
    BEGIN
        INSERT INTO dbo.t_StageInventory ( Vendor_Name, Model_Name, 
            AcquisitionDate, Qty )
        VALUES ( 'VendorName', 'ModelName', '20140101', 1 );
        SET @i = @i + 1;
    END;

    SET @i = 0;
    WHILE ( @i < 100 )
    BEGIN
        INSERT INTO dbo.t_StageInventory ( Vendor_Name, Model_Name, 
            AcquisitionDate, Qty )
        VALUES ( 'VendorName', 'ModelName', '20140102', 1 );
        SET @i = @i + 1;
    END;

    -- Insert data into the partitioned table;
    INSERT INTO dbo.Inventory ( AcquisitionDate, Vendor_Name, 
        Model_Name, Qty )
    SELECT  AcquisitionDate, Vendor_Name, Model_Name, Qty
    FROM    dbo.t_StageInventory;

    DROP TABLE dbo.t_StageInventory;

    SET NOCOUNT OFF;
END;
GO

データの分布を表示:

SELECT  ObjectName = OBJECT_NAME( p.object_id ),
        PartitionSchemeName = ps.name,
        PartitionFunctionName = pf.name,
        PartitionNumber = p.partition_number,
        FileGroup = fg.name,
        Rows = p.rows
FROM    sys.partitions p
INNER JOIN sys.indexes i
    ON  p.object_id = i.object_id
INNER JOIN sys.partition_schemes ps
    ON  i.data_space_id = ps.data_space_id
INNER JOIN sys.partition_functions pf
    ON  ps.function_id = pf.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
WHERE   p.object_id = OBJECT_ID( 'Inventory' );

テストがセットアップされたので、SWITCH の準備に進むことができます。ステージング テーブルが再び読み込まれます。

新しいステージ:

-- "Stage" data from ETL
SET NOCOUNT ON;

DECLARE @i      INTEGER;

CREATE TABLE dbo.t_StageInventory
(
    Inventory_PK        INTEGER IDENTITY( 1, 1 ) NOT NULL,
    AcquisitionDate     DATETIME NOT NULL,
                            PRIMARY KEY ( Inventory_PK, AcquisitionDate ),
    Vendor_Name         VARCHAR( 80 ) NULL,
    Model_Name          VARCHAR( 80 ) NULL,
    Qty                 BIGINT NOT NULL
) ON ps_DateRange( AcquisitionDate );

    SET @i = 0;
WHILE ( @i < 10 )
BEGIN
    INSERT INTO dbo.t_StageInventory ( Vendor_Name, Model_Name, 
        AcquisitionDate, Qty )
    VALUES ( 'VendorName', 'ModelName', '20140102', 1 );
    SET @i = @i + 1;
END;

SET @i = 0;
WHILE ( @i < 100 )
BEGIN
    INSERT INTO dbo.t_StageInventory ( Vendor_Name, Model_Name, 
        AcquisitionDate, Qty )
    VALUES ( 'VendorName', 'ModelName', '20140103', 1 );
    SET @i = @i + 1;
END;

ステージング テーブルにデータが入力されたら、レポート安定テーブルから転送する必要がある行を特定し、それらを移動する必要があります。

データの再ステージング:

-- Re-stage existing partition data;
DECLARE @UpperBound     DATETIME,
        @LowRange       DATETIME,
        @HighRange      DATETIME;
    SET @UpperBound = '99991231';

SELECT  @LowRange = MIN( CAST( pprv.value AS DATETIME ) ), 
        @HighRange = MAX( ISNULL( CAST( prv.value AS DATETIME ), @UpperBound ) )
FROM    sys.partitions p
INNER JOIN sys.indexes i
    ON  p.object_id = i.object_id
INNER JOIN sys.partition_schemes ps
    ON  i.data_space_id = ps.data_space_id
INNER JOIN sys.partition_functions pf
    ON  ps.function_id = pf.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 JOIN sys.partition_range_values prv
    ON  ps.function_id = prv.function_id
    AND p.partition_number = prv.boundary_id
LEFT JOIN sys.partition_range_values pprv
    ON  ps.function_id = prv.function_id
    AND p.partition_number - 1 = pprv.boundary_id
WHERE   p.object_id = OBJECT_ID( 't_StageInventory' )
    AND rows <> 0;

INSERT INTO dbo.t_StageInventory( AcquisitionDate, Vendor_Name, Model_Name, Qty )
SELECT  AcquisitionDate, Vendor_Name, Model_Name, Qty
FROM    dbo.Inventory
WHERE   AcquisitionDate >= @LowRange
    AND AcquisitionDate < @HighRange;

スイッチアウト、次にイン

CREATE TABLE dbo.t_SwapInventory
(
    Inventory_PK        INTEGER IDENTITY( 1, 1 ) NOT NULL,
    AcquisitionDate     DATETIME NOT NULL,
                            PRIMARY KEY ( Inventory_PK, AcquisitionDate ),
    Vendor_Name         VARCHAR( 80 ) NULL,
    Model_Name          VARCHAR( 80 ) NULL,
    Qty                 BIGINT NOT NULL
) ON ps_DateRange( AcquisitionDate );

-- Dynamic here...
DECLARE @t_Partition TABLE
(
    partition_number    INTEGER
);

INSERT INTO @t_Partition ( partition_number )
SELECT  DISTINCT p.partition_number
FROM    sys.partitions p
WHERE   p.object_id = OBJECT_ID( 't_StageInventory' )
    AND p.rows <> 0;
    SET @i = @@ROWCOUNT;

DECLARE @SQL            NVARCHAR( MAX ),
        @Partition      INTEGER;
WHILE ( @i > 0 )
BEGIN
    SELECT  TOP 1 @Partition = partition_number
    FROM    @t_Partition;

    DELETE  @t_Partition
    WHERE   partition_number = @Partition;

    SET @SQL = N'
        ALTER TABLE dbo.Inventory
        SWITCH PARTITION ' + LEFT( @Partition, 1024 ) + '
            TO dbo.t_SwapInventory PARTITION ' + LEFT( @Partition, 1024 ) + ';';
    EXECUTE dbo.sp_executesql @statement = @SQL;

    SET @SQL = N'
        ALTER TABLE dbo.t_StageInventory
        SWITCH PARTITION ' + LEFT( @Partition, 1024 ) + '
            TO dbo.Inventory PARTITION ' + LEFT( @Partition, 1024 ) + ';';
    EXECUTE dbo.sp_executesql @statement = @SQL;

    SET @i = @i - 1;
END;

GO
DROP TABLE dbo.t_SwapInventory;

DROP TABLE dbo.t_StageInventory;

SET NOCOUNT OFF;

この時点で、上記のデータ分布の表示クエリを実行して、追加の検証を行うことができます。

于 2014-01-14T17:05:56.393 に答える