質問

約220のテーブルを持つSQL Server 2000データベースがあります。これらのテーブルには、多数の外部キー関係があります。パフォーマンス分析により、これらの外部キー関係の多くがインデックスを欠いていることがわかりました。パフォーマンスの問題に対処する代わりに、積極的に対処して、インデックスが欠落しているすべての外部キーを見つけたいと思います。

どの外部キーにインデックスが欠落しているかをプログラムで判断するにはどうすればよいですか?

役に立ちましたか?

解決 2

同僚が作成したSQL Server 2000で有効な回答を次に示します。

/*
Description:
    This script outputs a table with all the current database un-indexed foreign keys.

    The table has three columns ( TableName , ColumnName, ForeignKeyName ) 
    TableName: The table containing the un-indexed foreign key
    ColumnName: The foreign key column that’s not indexed 
    ForeignKeyName: Name of foreign key witch column doesn’t have an index 
    */
DECLARE 
    @TableName varchar(255),
    @ColumnName varchar(255),
    @ForeignKeyName sysname

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DECLARE FKColumns_cursor CURSOR Fast_Forward FOR
SELECT  cu.TABLE_NAME, cu.COLUMN_NAME, cu.CONSTRAINT_NAME
FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS ic 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON ic.CONSTRAINT_NAME = cu.CONSTRAINT_NAME
WHERE   ic.CONSTRAINT_TYPE = 'FOREIGN KEY'

CREATE TABLE #temp1(    
    TableName varchar(255),
    ColumnName varchar(255),
    ForeignKeyName sysname
)

OPEN FKColumns_cursor  
FETCH NEXT FROM FKColumns_cursor INTO @TableName, @ColumnName, @ForeignKeyName

WHILE @@FETCH_STATUS = 0  
BEGIN

    IF ( SELECT COUNT(*)
    FROM    sysobjects o    
        INNER JOIN sysindexes x ON x.id = o.id
        INNER JOIN  syscolumns c ON o.id = c.id 
        INNER JOIN sysindexkeys xk ON c.colid = xk.colid AND o.id = xk.id AND x.indid = xk.indid
    WHERE   o.type in ('U')
        AND xk.keyno <= x.keycnt
        AND permissions(o.id, c.name) <> 0
        AND (x.status&32) = 0
        AND o.name = @TableName
        AND c.name = @ColumnName
    ) = 0
    BEGIN
        INSERT INTO #temp1 SELECT @TableName, @ColumnName, @ForeignKeyName
    END


    FETCH NEXT FROM FKColumns_cursor INTO @TableName, @ColumnName, @ForeignKeyName
END  
CLOSE FKColumns_cursor  
DEALLOCATE FKColumns_cursor 

SELECT * FROM #temp1 ORDER BY TableName

他のヒント

SELECT  *
FROM    sys.foreign_keys fk
WHERE   EXISTS
        (
        SELECT  *
        FROM    sys.foreign_key_columns fkc
        WHERE   fkc.constraint_object_id = fk.object_id
                AND NOT EXISTS
                (
                SELECT  *
                FROM    sys.index_columns ic
                WHERE   ic.object_id = fkc.parent_object_id
                        AND ic.column_id = fkc.parent_column_id
                        AND ic.index_column_id = fkc.constraint_column_id
                )
        )

SQL Server 2000 のコピーは手元にありませんが、 sys.foreign_key sysforeignkeys などに変更する必要がある場合があります。 、 here の説明のように。

このクエリは、キーを構成するすべての列をカバーするインデックスを持たないすべての外部キーを選択します。

これは、複数列の外部キーもサポートします。

ただし、これは、すべての列をカバーする複合インデックスがあるが、このインデックスの左端の列ではない場合、誤検知を返します。

同様に、 FOREIGN KEY(col2、col3)(col1、col2、col3)のインデックスがある場合、これはインデックスがあることを返しますこのインデックスはこの外部キーでは使用できないという事実にもかかわらず。

上記のコードに基づいて一時テーブルを削除し、インデックスを作成するスクリプトを取得します。

   /*
Description:

    */
DECLARE 
    @SchemaName varchar(255),
    @TableName varchar(255),
    @ColumnName varchar(255),
    @ForeignKeyName sysname

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

DECLARE FKColumns_cursor CURSOR Fast_Forward FOR
SELECT  cu.TABLE_SCHEMA, cu.TABLE_NAME, cu.COLUMN_NAME, cu.CONSTRAINT_NAME
FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS ic 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu ON ic.CONSTRAINT_NAME = cu.CONSTRAINT_NAME
WHERE   ic.CONSTRAINT_TYPE = 'FOREIGN KEY'

CREATE TABLE #temp1(    
    SchemaName varchar(255),
    TableName varchar(255),
    ColumnName varchar(255),
    ForeignKeyName sysname
)

OPEN FKColumns_cursor  
FETCH NEXT FROM FKColumns_cursor INTO @SchemaName,@TableName, @ColumnName, @ForeignKeyName

WHILE @@FETCH_STATUS = 0  
BEGIN

    IF ( SELECT COUNT(*)
    FROM        sysobjects o    
        INNER JOIN sysindexes x ON x.id = o.id
        INNER JOIN  syscolumns c ON o.id = c.id 
        INNER JOIN sysindexkeys xk ON c.colid = xk.colid AND o.id = xk.id AND x.indid = xk.indid
    WHERE       o.type in ('U')
        AND xk.keyno <= x.keycnt
        AND permissions(o.id, c.name) <> 0
        AND (x.status&32) = 0
        AND o.name = @TableName
        AND c.name = @ColumnName
    ) = 0
    BEGIN
        INSERT INTO #temp1 SELECT @SchemaName, @TableName, @ColumnName, @ForeignKeyName
    END


    FETCH NEXT FROM FKColumns_cursor INTO @SchemaName,@TableName, @ColumnName, @ForeignKeyName
END  
CLOSE FKColumns_cursor  
DEALLOCATE FKColumns_cursor 

SELECT 'CREATE INDEX IDX_' + ForeignKeyName + ' ON ' + SchemaName + '.' + TableName + '(' + ColumnName +')'
FROM #temp1 
ORDER BY TableName

drop table #temp1 

まず:外部キー制約のある列をリストします。これが役立ちます:

クエリでSQLのすべての外部キー制約を取得サーバー2000

sysindexes および syscolumns テーブルとのクロス比較。 sysindexes keys フィールドには、インデックス内のすべてのキーのリストがあります。

注:これはSQL Server 2005+向けですが、このトピックについて私が見つけた唯一の質問でした。

--Finds foreign keys without indexes
--How to interpret:
--When we delete frpm PkTable, it checks FkColumn for the PkId we are deleting.
--So if FkTable doesn't have an index on FkColumn, then we cannot delete a row from PkTable because it is too slow.
SELECT  rt.name as PkTableName, rc.name as PkColumnName,
fk.name FkName, t.name as FkTableName, c.name as FkColumnName, ddps.row_count, i.name as IndexName
FROM    sys.foreign_key_columns fkc
inner join sys.foreign_keys fk on fkc.constraint_object_id = fk.object_id
inner join sys.tables t on fkc.parent_object_id = t.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.tables rt on fkc.referenced_object_id = rt.object_id
inner join sys.columns rc on fkc.referenced_object_id = rc.object_id and fkc.referenced_column_id = rc.column_id
inner join sys.indexes ri on t.object_id = ri.object_id
inner JOIN sys.dm_db_partition_stats AS ddps ON ri.OBJECT_ID = ddps.OBJECT_ID AND ri.index_id = ddps.index_id 
left join sys.index_columns ic on ic.object_id = t.object_id and ic.column_id = c.column_id
left join sys.indexes i on ic.object_id = i.object_id and i.index_id = ic.index_id
where ri.index_id < 2 and i.index_id is null and ddps.row_count > 0
order by 
--PkTableName,
ddps.row_count desc
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top