web-dev-qa-db-ja.com

多くの外部キーによって引き起こされる遅い削除

私のDBには約90のテーブルがあります。ほとんどのテーブルには、ユーザーテーブルを指す外部キーを持つUpdatedBy列とAddedBy列があります。データベース全体に適度な量のデータが分散しているため、古いユーザーレコードを削除するときに、削除プロセスが非常に遅くなります。

削除クエリは、まず現在のユーザーへのすべての更新/追加参照を更新し、次にユーザーレコードを削除します。実行プランには、外部キーによる関連する各テーブルのテーブルスキャンが表示されます。 私たちが直面していることの例としてこの投稿を参照してください

追加および更新へのポインターは、アプリケーションの問題の分析以外にはあまり役に立ちません。それらはめったに使用されず、それらが使用されたときに優れた情報の主要な情報源ではありません。外部キー制約をすべて削除する必要があるのか​​、またはテーブル名、列、値、ユーザーIDのレコードを保持する別のテーブルに更新の監査を移動する必要があるのか​​、それとも他に何かあるのかと思います。 DBAコミュニティがこの種の状況に引き寄せられる一般的に受け入れられているアプローチ。

5
Josh

Dbmsは参照テーブルでそれらの列を使用してルックアップを実行するため、制約された列にインデックスがあることを確認してください。

このスクリプトを使用してみると、カスケード制約によって参照されているインデックス付けされていない列のインデックス作成スクリプトが生成されます。

SELECT 'CREATE NONCLUSTERED INDEX IX_'+OBJECT_NAME(fk.parent_object_id)+'_'+c.name+' ON '+OBJECT_NAME(fk.parent_object_id)+'('+c.name+') WITH (ONLINE=ON)' 
        --, OBJECT_NAME(fk.referenced_object_id) AS referenced_tale,  cc.name
FROM 
    sys.foreign_keys fk
    INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
    INNER JOIN sys.columns c ON fkc.parent_object_id = c.object_id AND fkc.parent_column_id = c.column_id
    INNER JOIN sys.columns cc ON fkc.referenced_object_id = cc.object_id AND fkc.referenced_column_id = cc.column_id
WHERE delete_referential_action_desc IN ('CASCADE', 'SET_NULL')
    AND NOT EXISTS
        (
        SELECT  1
        FROM
            SYS.index_columns ic 
            INNER JOIN sys.indexes i ON i.object_id = ic.object_id AND ic.index_id = i.index_id
        WHERE 
            1 = 1
            AND type_DESC IN ('CLUSTERED','NONCLUSTERED')
            AND ic.OBJECT_ID = c.object_id
            AND ic.column_id = c.column_id
            AND ic.is_included_column = 0
        )
10
druzin