外键多导致删除慢

Jos*_*osh 5 performance foreign-key database-design sql-server

我的数据库有大约 90 个表。大多数表都有一个UpdatedBy 和AddedBy 列,它们的外键指向用户表。即使在整个数据库中散布适量的数据,这也会导致在清除旧用户记录时的删除过程非常缓慢。

我们的删除查询首先更新当前用户的所有更新/添加引用,然后删除用户记录。由于外键,执行计划显示每个相关表的表扫描。请参阅这篇文章作为我们面临的一个例子

除了用于分析应用程序问题之外,返回添加和更新的指针并没有真正有用。它们很少使用,并且在它们使用时不是良好信息的主要来源。我想知道是否应该一起删除外键约束,或者是否应该将更新审计转移到一个单独的表中,该表保留表名、列、值和用户 ID 的记录,或者是否还有其他一些DBA 社区在这种情况下倾向于采用的普遍接受的方法。

dru*_*zin 10

确保受约束的列上有索引,因为 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
        )
Run Code Online (Sandbox Code Playgroud)

  • 我认为您还需要“AND ic.key_ordinal = 1”,因为该列可能位于某个索引中,但如果它不是第一列,则无法快速查找。 (2认同)