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

SQL Server 自動化された毎日のテーブル パーティション分割

    スライディング ウィンドウ パーティションのメンテナンスは通常、スケジュールされたスクリプトまたはストアド プロシージャ (SQL Server エージェント ジョブまたはその他のスケジュール システム) を使用して行われます。 SPLIT 中のコストのかかるデータ移動を避けるために、メンテナンスを計画する必要があります。 および MERGE 通常の DML 操作の約 4 倍のログが必要になるためです。このために、 MERGE の前に、境界値を含むパーティションが空であることを確認してください SPLIT の場合、指定された境界を超える行はありません .メンテナンスが計画どおりに実行されない場合に備えて、データの移動を回避するためのバッファーとして、いくつかの追加の将来のパーティションを作成することをお勧めします。

    以下は、毎日のスライディング ウィンドウ メンテナンス スクリプトの例です。これは、SQL Server 2005 とパーティション レベルの TRUNCATE を使用しているため、同様にパーティション分割されたステージング テーブルをパージに使用します。 は SQL Server 2016 で導入されました。SQL Server 2005 はサポートされていないことに注意してください。

    あなたのコメントから、パーティションごとに個別のファイルグループ/ファイルがパーティションを削除するのに役立つと思われることがわかりますが、そうではありません。この例では、すべてのパーティションに対して 1 つのファイル グループを使用しています。

    --example setup
    CREATE PARTITION FUNCTION PF_Date (datetime) AS
        RANGE RIGHT FOR VALUES();
    CREATE PARTITION SCHEME PS_LogTable AS
        PARTITION PF_Date ALL TO ([PRIMARY]);
    DECLARE @PartitionBoundaryDate datetime = DATEADD(day, -31, DATEADD(day, DATEDIFF(day, '', GETDATE()), ''));
    
    WHILE @PartitionBoundaryDate < DATEADD(day, 1, GETDATE())
    BEGIN
        ALTER PARTITION SCHEME PS_LogTable NEXT USED [PRIMARY];
        ALTER PARTITION FUNCTION PF_Date() SPLIT RANGE(@PartitionBoundaryDate);
        SET @PartitionBoundaryDate = DATEADD(day, 1, @PartitionBoundaryDate)
    END;
    CREATE TABLE dbo.LogTable(DateColumn datetime INDEX cdx CLUSTERED) ON PS_LogTable(DateColumn);
    CREATE TABLE dbo.LogTable_Staging(DateColumn datetime INDEX cdx CLUSTERED) ON PS_LogTable(DateColumn);
    GO
    
    --example partition maintenance scheduled nightly after midnight
    BEGIN TRY
        SET NOCOUNT ON;
        SET XACT_ABORT ON;
        DECLARE @RetentionDays int = 31;
        DECLARE @FutureDays int = 7;
        DECLARE @OldestRetainedDate datetime = DATEADD(day, [email protected], DATEADD(day, DATEDIFF(day, '', GETDATE()), ''));
        DECLARE @LatestRetainedDate datetime = DATEADD(day, DATEDIFF(day, '', GETDATE()), '');
        DECLARE @LatestFutureBoundaryDate datetime = DATEADD(day, @FutureDays, @LatestRetainedDate);
        DECLARE @PartitionBoundaryDate datetime;
        DECLARE @Message nvarchar(2048);
    
        --make sure staging table is empty
        TRUNCATE TABLE dbo.LogTable_Staging;
    
        BEGIN TRAN;
        --aquire exclusive table lock to avoid deadlocking during maintenance
        SELECT TOP(0) @PartitionBoundaryDate = DateColumn FROM dbo.LogTable WITH(TABLOCKX);
    
        --purge partition 1 in case data older than the first boundary was inserted
        SET @Message = 'Purging partition 1';
        PRINT @Message;
        ALTER TABLE dbo.LogTable SWITCH
            PARTITION 1 TO
            dbo.LogTable_Staging PARTITION 1;
        TRUNCATE TABLE dbo.LogTable_Staging;
    
        --purge and remove expired partitions
        DECLARE @PartitionBoundaries TABLE(PartitionBoundaryDate datetime NOT NULL PRIMARY KEY);
        INSERT INTO @PartitionBoundaries(PartitionBoundaryDate)
            SELECT CAST(prv.value AS datetime)
            FROM sys.partition_functions AS pf
            JOIN sys.partition_range_values AS prv ON prv.function_id = pf.function_id
            WHERE
                pf.name = N'PF_Date'
                AND CAST(prv.value AS datetime) < @OldestRetainedDate;
        DECLARE ExpiredPartitionBoundaries CURSOR LOCAL FAST_FORWARD FOR
            SELECT PartitionBoundaryDate
            FROM @PartitionBoundaries;
    
        OPEN ExpiredPartitionBoundaries;
        WHILE 1 = 1
        BEGIN
            FETCH NEXT FROM ExpiredPartitionBoundaries INTO @PartitionBoundaryDate;
            IF @@FETCH_STATUS = -1 BREAK;
            SET @Message = 'Purging data for ' + CONVERT(char(10), @PartitionBoundaryDate, 120);
            PRINT @Message;
            ALTER TABLE dbo.LogTable SWITCH
                PARTITION $PARTITION.PF_Date(@PartitionBoundaryDate) TO
                dbo.LogTable_Staging PARTITION $PARTITION.PF_Date(@PartitionBoundaryDate);
            TRUNCATE TABLE dbo.LogTable_Staging;
            ALTER PARTITION FUNCTION PF_Date() MERGE RANGE(@PartitionBoundaryDate);
        END;
        CLOSE ExpiredPartitionBoundaries;
        DEALLOCATE ExpiredPartitionBoundaries;
    
        --create partitions for future days
        SET @PartitionBoundaryDate = DATEADD(day, 1, @LatestRetainedDate);
        WHILE @PartitionBoundaryDate < = @LatestFutureBoundaryDate
        BEGIN
            IF NOT EXISTS(SELECT 1
                FROM sys.partition_functions AS pf
                JOIN sys.partition_range_values AS prv ON prv.function_id = pf.function_id
                WHERE
                    pf.name = N'PF_Date'
                    AND CAST(prv.value AS datetime) = @PartitionBoundaryDate
            )
            BEGIN
                SET @Message = 'Creating partition for ' + CONVERT(char(10), @PartitionBoundaryDate, 120);
                PRINT @Message;
                ALTER PARTITION SCHEME PS_LogTable NEXT USED [PRIMARY];
                ALTER PARTITION FUNCTION PF_Date() SPLIT RANGE(@PartitionBoundaryDate);
            END;
            SET @PartitionBoundaryDate = DATEADD(day, 1, @PartitionBoundaryDate);
        END;
    
        COMMIT;
    END TRY
    BEGIN CATCH
    
        IF @@TRANCOUNT > 0 ROLLBACK;
    
        --better to use THROW in SQL 2012 and later
        DECLARE
             @ErrorNumber int
            ,@ErrorMessage nvarchar(2048)
            ,@ErrorSeverity int
            ,@ErrorState int
            ,@ErrorLine int;
    
        SELECT
            @ErrorNumber =ERROR_NUMBER()
            ,@ErrorMessage =ERROR_MESSAGE()
            ,@ErrorSeverity = ERROR_SEVERITY()
            ,@ErrorState =ERROR_STATE()
            ,@ErrorLine =ERROR_LINE();
    
        RAISERROR('Error %d caught at line %d: %s'
            ,@ErrorSeverity
            ,@ErrorState
            ,@ErrorNumber
            ,@ErrorLine
            ,@ErrorMessage);
    
    END CATCH;
    GO
    



    1. OracleSQLステートメントの行を集約

    2. TypeError:'NoneType'オブジェクトはFlask、mysqlアプリケーションで添え字化できません

    3. JSP /サーブレット:zipファイルをアップロードして解凍し、CSVファイルを抽出するにはどうすればよいですか。

    4. 開始日と終了日の間の日付の検索