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

DBCCCHECKCONSTRAINTSとI/Oを見てください

    データベース設計で使用される一般的な要素は制約です。制約にはさまざまなフレーバー(デフォルト、一意など)があり、制約が存在する列の整合性を強制します。適切に実装された場合、制約は、設定された基準を満たさないデータがデータベースに入るのを防ぐため、データベースの設計における強力なコンポーネントです。ただし、WITH NOCHECKなどのコマンドを使用すると、制約に違反する可能性があります。 およびIGNORE_CONSTRAINTS 。また、REPAIR_ALLOW_DATA_LOSSを使用する場合 DBCC CHECKのオプション データベースの破損を修復するコマンド。制約は考慮されません。

    その結果、データベースに無効なデータが存在する可能性があります。制約に準拠していないデータ、または期待される主キーと外部キーの関係を維持しなくなったデータのいずれかです。 SQL Serverには、DBCC CHECKCONSTRAINTSが含まれています 制約に違反するデータを検索するステートメント。修復オプションが実行されたら、DBCC CHECKCONSTRAINTSを実行します データベース全体で問題がないことを確認し、CHECKCONSTRAINTSを実行することが適切な場合があります。 選択制約またはテーブルの場合。データの整合性を維持することは重要であり、DBCC CHECKCONSTRAINTSを実行することは一般的ではありませんが 無効なデータを定期的に見つけて実行する必要がある場合は、データがもたらす可能性のあるパフォーマンスへの影響を理解することをお勧めします。

    DBCC CHECKCONSTRAINTS 単一の制約、テーブル、またはデータベース全体に対して実行できます。他のチェックコマンドと同様に、完了するまでにかなりの時間がかかる可能性があり、特に大規模なデータベースの場合、システムリソースを消費します。他のチェックコマンドとは異なり、CHECKCONSTRAINTS データベーススナップショットを使用しません。

    拡張イベントを使用すると、DBCC CHECKCONSTRAINTSを実行するときにリソースの使用状況を調べることができます。 テーブルのために。影響をよりよく示すために、Jonathan Kehayias(ブログ| @SQLPoolBoy)からCreate Enlarged AdventureWorks Tables.sqlスクリプトを実行して、より大きなテーブルを作成しました。 Jonathanのスクリプトはテーブルのインデックスのみを作成するため、選択したいくつかの制約を追加するには、以下のステートメントが必要です。

    USE [AdventureWorks2012];
    GO
     
    ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
    WITH CHECK ADD CONSTRAINT [FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID]
    FOREIGN KEY([SalesOrderID])
    REFERENCES [Sales].[SalesOrderHeaderEnlarged] ([SalesOrderID])
    ON DELETE CASCADE;
    GO
     
    ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
    WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_OrderQty]
    CHECK (([OrderQty]>(0)))
    GO
     
    ALTER TABLE [Sales].[SalesOrderDetailEnlarged]
    WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_UnitPrice]
    CHECK (([UnitPrice]>=(0.00)));
    GO
     
    ALTER TABLE [Sales].[SalesOrderHeaderEnlarged]
    WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_DueDate]
    CHECK (([DueDate]>=[OrderDate]))
    GO
     
    ALTER TABLE [Sales].[SalesOrderHeaderEnlarged]
    WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_Freight]
    CHECK (([Freight]>=(0.00)))
    GO

    sp_helpconstraintを使用して、どのような制約が存在するかを確認できます :

    EXEC sp_helpconstraint '[Sales].[SalesOrderDetailEnlarged]';
    GO


    sp_helpconstraint出力

    制約が存在する場合、DBCC CHECKCONSTRAINTSのリソース使用量を比較できます。 単一の制約、テーブル、および拡張イベントを使用するデータベース全体の場合。まず、sp_statement_completedをキャプチャするだけのセッションを作成します イベント、sql_textを含む アクションを実行し、出力をring_bufferに送信します :

    CREATE EVENT SESSION [Constraint_Performance] ON SERVER
    ADD EVENT sqlserver.sp_statement_completed
    (
      ACTION(sqlserver.database_id,sqlserver.sql_text)
    )
    ADD TARGET package0.ring_buffer
    (
      SET max_events_limit=(5000)
    )
    WITH 
    (
        MAX_MEMORY=32768 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
        MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB,
        MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=OFF
    );
    GO

    次に、セッションを開始して、各DBCC CHECKCONSTRAINTを実行します。 コマンドを実行し、リングバッファを一時テーブルに出力して操作します。 DBCC DROPCLEANBUFFERSに注意してください 各チェックの前に実行されるため、各チェックはコールドキャッシュから開始され、レベルのテストフィールドが維持されます。

    ALTER EVENT SESSION [Constraint_Performance]
    ON SERVER
    STATE=START;
    GO
     
    USE [AdventureWorks2012];
    GO
     
    DBCC DROPCLEANBUFFERS;
    GO
    DBCC CHECKCONSTRAINTS ('[Sales].[CK_SalesOrderDetailEnlarged_OrderQty]') WITH NO_INFOMSGS;
    GO
    DBCC DROPCLEANBUFFERS;
    GO
    DBCC CHECKCONSTRAINTS ('[Sales].[FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID]') WITH NO_INFOMSGS;
    GO
    DBCC DROPCLEANBUFFERS;
    GO
    DBCC CHECKCONSTRAINTS ('[Sales].[SalesOrderDetailEnlarged]') WITH NO_INFOMSGS;
    GO
    DBCC DROPCLEANBUFFERS;
    GO
    DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS, NO_INFOMSGS;
    GO
     
    DECLARE @target_data XML;
     
    SELECT @target_data = CAST(target_data AS XML)
      FROM sys.dm_xe_sessions AS s
      INNER JOIN sys.dm_xe_session_targets AS t 
      ON t.event_session_address = s.[address]
      WHERE s.name = N'Constraint_Performance'
      AND t.target_name = N'ring_buffer';
     
    SELECT
      n.value('(@name)[1]', 'varchar(50)') AS event_name,
      DATEADD(HOUR ,DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME()),n.value('(@timestamp)[1]', 'datetime2')) AS [timestamp],
      n.value('(data[@name="duration"]/value)[1]', 'bigint') AS duration,
      n.value('(data[@name="physical_reads"]/value)[1]', 'bigint') AS physical_reads,
      n.value('(data[@name="logical_reads"]/value)[1]', 'bigint') AS logical_reads,
      n.value('(action[@name="sql_text"]/value)[1]', 'varchar(max)') AS sql_text,
      n.value('(data[@name="statement"]/value)[1]', 'varchar(max)') AS [statement]
    INTO #EventData
    FROM @target_data.nodes('RingBufferTarget/event[@name=''sp_statement_completed'']') AS q(n);
    GO
     
    ALTER EVENT SESSION [Constraint_Performance]
    ON SERVER
    STATE=STOP;
    GO

    ring_bufferの解析 一時テーブルへの入力にはさらに時間がかかる場合がありますが(私のマシンでは約20秒)、データの繰り返しクエリは、ring_bufferを介するよりも一時テーブルからの方が高速です。 。出力を見ると、DBCC CHECKCONSTRAINTSごとにいくつかのステートメントが実行されていることがわかります。 :

    SELECT *
    FROM #EventData
    WHERE [sql_text] LIKE 'DBCC%';


    拡張イベント出力

    拡張イベントを使用して、CHECKCONSTRAINTSの内部動作を掘り下げます これは興味深いタスクですが、ここで本当に関心があるのは、リソースの消費、特にI/Oです。 physical_readsを集約できます I / Oを比較するためのチェックコマンドごとに:

    SELECT [sql_text], SUM([physical_reads]) AS [Total Reads]
    FROM #EventData
    WHERE [sql_text] LIKE 'DBCC%'
    GROUP BY [sql_text];


    小切手の集約I/O

    制約を確認するには、SQL Serverがデータを読み取って、制約に違反している可能性のある行を見つける必要があります。 CK_SalesOrderDetailEnlarged_OrderQtyの定義 制約は[OrderQty] > 0です 。外部キー制約、FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderIDSalesOrderIDで関係を確立します [Sales].[SalesOrderHeaderEnlarged]の間 および[Sales].[SalesOrderDetailEnlarged] テーブル。 SQL Serverは2つのテーブルからデータを読み取る必要があるため、直感的には、外部キー制約をチェックするためにより多くのI/Oが必要になるように見える場合があります。ただし、[SalesOrderID] IX_SalesOrderHeaderEnlarged_SalesPersonIDのリーフレベルに存在します [Sales].[SalesOrderHeaderEnlarged]の非クラスター化インデックス テーブル、およびIX_SalesOrderDetailEnlarged_ProductID [Sales].[SalesOrderDetailEnlarged]のインデックス テーブル。そのため、SQL Serverはこれら2つのインデックスをスキャンして、[SalesOrderID]を比較します。 2つのテーブル間の値。これには、19,000回を超える読み取りが必要です。 CK_SalesOrderDetailEnlarged_OrderQtyの場合 制約、[OrderQty] 列はどのインデックスにも含まれていないため、クラスター化インデックスのフルスキャンが実行され、72,000回を超える読み取りが必要になります。

    テーブルのすべての制約がチェックされると、I / O要件は、単一の制約がチェックされる場合よりも高くなり、データベース全体がチェックされると再び増加します。上記の例では、[Sales].[SalesOrderHeaderEnlarged] および[Sales].[SalesOrderDetailEnlarged] テーブルは、データベース内の他のテーブルよりも不釣り合いに大きくなります。これは、実際のシナリオでは珍しいことではありません。多くの場合、データベースには、データベースの大部分を構成するいくつかの大きなテーブルがあります。 CHECKCONSTRAINTSを実行する場合 これらのテーブルでは、チェックに必要な潜在的なリソース消費に注意してください。ユーザーへの影響を最小限に抑えるために、可能な場合は営業時間外にチェックを実行してください。通常の営業時間中にチェックを実行する必要がある場合は、どの制約が存在し、検証をサポートするためにどのインデックスが存在するかを理解すると、チェックの効果を評価するのに役立ちます。最初にテスト環境または開発環境でチェックを実行してパフォーマンスへの影響を理解できますが、ハードウェアや比較可能なデータなどに基づいてバリエーションが存在する可能性があります。最後に、REPAIR_ALLOW_DATA_LOSS オプションの場合は、DBCC CHECKCONSTRAINTSを使用して修復します 。破損が修正されるため、データベースの修復では制約が考慮されないため、データが失われる可能性があることに加えて、データベース内の1つ以上の制約に違反するデータが発生する可能性があります。


    1. SQLクエリを高速化する方法

    2. Mavenの依存関係としてPostgreSQLドライバーをどのように追加しますか?

    3. SQLServerのVIEWS情報スキーマビューを使用してビュー情報を取得する

    4. SQL Serverリストテーブル:すべてのテーブルを表示する方法