sql >> データベース >  >> RDS >> Sqlserver

SQL Server(T-SQL)でパーティションテーブルを作成する

    SQL Serverは、パーティション化されたテーブルとインデックスをサポートしています。パーティション化されたテーブルまたはインデックスがパーティション化されると、そのデータは複数のファイルグループに分散できるユニットに分割されます。

    したがって、SQL Serverでパーティションテーブルを作成するには、最初に各パーティションを保持するファイルグループを作成する必要があります。また、パーティション関数とパーティションスキームを作成する必要があります。

    つまり、次のようになります:

    1. ファイルグループを作成する
    2. パーティション関数を作成する
    3. パーティションスキームを作成する
    4. パーティションテーブルを作成する

    以下は、これらの手順を使用して4つのパーティションを持つテーブルを作成する例です。

    ファイルグループの作成

    まず、テストという4つのファイルグループをデータベースに追加します。 、次に、これらの各ファイルグループの物理ファイルを指定します。

    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  

    要件に応じて、このコードを変更する必要があります。また、環境に合わせてファイルパスを変更する必要があります。たとえば、Windowsを使用している場合、パスはD:\mssql\data\MoviesFg4dat.ndfのようになります。 。

    また、より多くのパーティションが必要な場合は、ここにファイルグループを追加してください。逆に、必要なパーティションが少ない場合は、ここで指定するファイルグループを少なくしてください。

    パーティション関数を作成する

    次に、 MoviesPartitionFunctionというパーティション関数を作成します これにより、テーブルが4つのパーティションに分割されます。

    CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
        AS RANGE LEFT FOR VALUES (1, 100, 1000);
    GO

    int partは、パーティショニングに使用される列のデータ型を指定します。

    テキストを除くすべてのデータ型は、パーティション列としての使用に有効です。 、 ntext 画像 xml タイムスタンプ varchar(max) nvarchar(max) varbinary(max) 、エイリアスデータ型、またはCLRユーザー定義データ型。

    ここでは、3つの境界値(1、100)を使用します 、および1000 )4つのパーティションを指定します。これらの境界値は、パーティション関数の名前の後に括弧で囲まれたデータ型と一致するか、暗黙的に変換可能である必要があります。

    これらの境界値と、RANGE LEFTを指定したという事実を考えると パーティションの場合、4つのパーティションは次の表に指定されている値を保持します。

    パーティション
    1 <=1
    2 > 1 AND <=100
    3 > 100 AND <=1000
    4 > 1000

    RANGE RIGHTを指定した場合 次の表に示すように、パーティションの内訳はわずかに異なります。

    パーティション
    1 <1
    2 > =1 AND <100
    3 > =100 AND <1000
    4 > =1000

    パーティショニング列が日付/時刻値などの他のデータ型を使用する場合も、同じ概念が適用されます。

    パーティションスキームを作成する

    次に、パーティションスキームを作成する必要があります。

    パーティションスキームは、パーティション化されたテーブルまたはインデックスのパーティションを新しいファイルグループにマップします。

    この場合、コードは次のようになります。

    CREATE PARTITION SCHEME MoviesPartitionScheme  
        AS PARTITION MoviesPartitionFunction  
        TO (MoviesFg1, MoviesFg2, MoviesFg3, MoviesFg4);  
    GO

    前の手順で作成したパーティション関数を参照していることに注意してください。また、最初のステップで作成したファイルグループも参照します。

    パーティションテーブルを作成する

    最後に、パーティションテーブルを作成できます。

    CREATE TABLE Movies (
        MovieId int IDENTITY PRIMARY KEY, 
        MovieName varchar(60)
        )  
        ON MoviesPartitionScheme (MovieId);  
    GO

    これとパーティション化されていないテーブルの作成の唯一の違いは、パーティション化されたテーブルを作成するときに、ONを使用することです。 使用するパーティションスキームを指定する引数。この例では、前の手順で作成したパーティションスキームを指定し、 MovieIdを指定します。 分割列としての列。

    MovieId 列のデータ型はint 、これは、パーティション関数の作成時に指定した境界値と一致します。

    パーティション関数で計算列を使用する場合は、明示的にPERSISTEDとマークする必要があることに注意してください。 。

    パーティション関数を確認する

    sys.partition_functionsを使用できます すべてのパーティション関数を返すために表示します。

    SELECT * FROM sys.partition_functions;

    結果(垂直出力を使用):

    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

    パーティションスキームを確認する

    sys.partition_schemesを使用できます パーティションスキームを確認します。

    SELECT * FROM sys.partition_schemes;

    結果(垂直出力を使用):

    name          | MoviesPartitionScheme
    data_space_id | 65601
    type          | PS
    type_desc     | PARTITION_SCHEME
    is_default    | 0
    is_system     | 0
    function_id   | 65536

    または、次のクエリを使用して、スキーマ、テーブル、インデックスなどの他の詳細を返すこともできます。

    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;

    結果(垂直出力を使用):

    Schema           | dbo
    Object           | Movies
    Index            | PK__Movies__4BD2941A0ED85ACA
    Partition Scheme | MoviesPartitionScheme

    パーティションテーブルを確認する

    sys.dm_db_partition_statsを実行できます 現在のデータベース内のすべてのパーティションのページと行数の情報を返すために表示します。

    ただし、テーブルにデータを挿入する前にそれを実行すると、ほとんどの統計がゼロになります。

    そこで、最初にデータを挿入します。

    INSERT INTO Movies
    SELECT name FROM OtherDb.dbo.Movies;

    結果:

    (4079 rows affected)

    4,079行が挿入されたことがわかります。

    それでは、sys.dm_db_partition_statsにクエリを実行してみましょう。 ビュー。

    SELECT *
    FROM sys.dm_db_partition_stats
    WHERE object_id = OBJECT_ID('dbo.Movies');

    結果:

    +-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+
    | 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        |
    +-------------------+-------------+------------+--------------------+--------------------------+--------------------------+------------------------------+-----------------------+---------------------------+--------------------------------+------------------------------------+-------------------+-----------------------+-------------+

    このビューは多くの列を返すので、列を2つだけに絞り込みましょう。

    SELECT 
        partition_number,
        row_count
    FROM sys.dm_db_partition_stats
    WHERE object_id = OBJECT_ID('dbo.Movies');

    結果:

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

    行がパーティション間でどのように割り当てられているかを確認できます。それらは、パーティション関数で指定したとおりに正確に割り当てられます。行の合計は4,079で、これは正確に挿入した行数です。

    ただし、Microsoftのドキュメントには、この列は単なる概算であると実際に記載されていることに注意してください。 各パーティションの行数。

    ベストプラクティス

    Microsoftは、パーティション範囲の両端に常に空のパーティションを保持することをお勧めします。

    これは、将来パーティションを分割またはマージする必要がある場合に備えています。

    この推奨の理由は、パーティションの分割とパーティションのマージによって予期しないデータ移動が発生しないことを保証するためです。

    したがって、私の例のデータを考えると、パーティション関数を次のように変更できます。

    CREATE PARTITION FUNCTION MoviesPartitionFunction (int)  
        AS RANGE LEFT FOR VALUES (-1, 100, 10000);
    GO

    または、10,000行を超えると予想される場合は、より多くの数を使用する(またはより多くのパーティションを作成する)ことができます。

    すべてのステップを再作成してパーティションテーブルを作成すると、パーティション統計は次のようになります。

    SELECT 
        partition_number,
        row_count
    FROM sys.dm_db_partition_stats
    WHERE object_id = OBJECT_ID('dbo.Movies');

    結果:

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

    現在、私のデータは中央の2つのパーティションに集中しており、両端のパーティションは空です。


    1. このCLOBフィールドのGetOrdinal関数でOutOfRange例外が発生するのはなぜですか?

    2. PostgreSQL DATEADD()と同等

    3. ORACLE_HOMEのクローン

    4. MySQLでVALUESステートメントを使用する場合の「エラー1136(21S01):列数が行2の値数と一致しない」を修正