データベース設計で使用される一般的な要素は制約です。制約にはさまざまなフレーバー(デフォルト、一意など)があり、制約が存在する列の整合性を強制します。適切に実装された場合、制約は、設定された基準を満たさないデータがデータベースに入るのを防ぐため、データベースの設計における強力なコンポーネントです。ただし、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つ以上の制約に違反するデータが発生する可能性があります。