データベース設計で使用される一般的な要素は制約です。制約にはさまざまなフレーバー(デフォルト、一意など)があり、制約が存在する列の整合性を強制します。適切に実装された場合、制約は、設定された基準を満たさないデータがデータベースに入るのを防ぐため、データベースの設計における強力なコンポーネントです。ただし、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];
制約を確認するには、SQL Serverがデータを読み取って、制約に違反している可能性のある行を見つける必要があります。 CK_SalesOrderDetailEnlarged_OrderQty
の定義 制約は[OrderQty] > 0
です 。外部キー制約、FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID
、SalesOrderID
で関係を確立します [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つ以上の制約に違反するデータが発生する可能性があります。