在每个外键上添加索引的脚本?

时间:2010-02-22 09:20:36

标签: sql-server indexing foreign-keys

在SQL Server中看到foreign key does not automatically create an index,我想在我的数据库中的每个FK字段上创建一个显式索引。我在模式中有超过100个表...

那么,是否有人有一个现成的打包脚本,我可以用来检测所有FK并在每个FK上创建一个索引?

5 个答案:

答案 0 :(得分:9)

好吧,我自己解决了这个问题 - 这是为了其他人的利益......

select 'create index IX_'+c.name+'_'+p.name+' on '+c.name+'('+cf.name+');'
from sysforeignkeys fk join sysobjects c on fk.fkeyid=c.id
join sysobjects p on fk.rkeyid=p.id
join syscolumns cf on c.id=cf.id and cf.colid = fk.fkey
left join sysindexkeys k on k.id = cf.id and k.colid = cf.colid
where k.id is null
order by c.name

它不能100%工作,例如,如果一个表上有两个FK到同一个主表,但是有足够的实例(至少在我的数据库中),我可以手动纠正这些

答案 1 :(得分:8)

好的,这是我对此的看法。我添加了对方案的支持,并检查是否存在具有当前命名约定的索引。这样,在修改表时,可以检查缺失的索引。

   SELECT 'CREATE NONCLUSTERED INDEX IX_' + s.NAME + '_' + o.NAME + '__' + c.NAME + ' ON ' + s.NAME + '.' + o.NAME + ' (' + c.NAME + ')'
    FROM sys.foreign_keys fk
    INNER JOIN sys.objects o ON fk.parent_object_id = o.object_id
    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.tables t ON t.object_id = o.object_id
    INNER JOIN sys.schemas s ON s.schema_id = t.schema_id
    LEFT JOIN sys.indexes i ON i.NAME = ('IX_' + s.NAME + '_' + o.NAME + '__' + c.NAME)
    WHERE i.NAME IS NULL
    ORDER BY o.NAME

答案 2 :(得分:3)

我修改了查询以使用它们的系统视图。它还会编写表格中的每个FK而不仅仅是一个。

SELECT 'CREATE NONCLUSTERED INDEX ndx_' + o.name + '__' + c.name 
   + ' ON ' + o.name + ' (' + c.name + ')'
FROM   sys.foreign_keys        fk
JOIN   sys.objects             o    ON  fk.parent_object_id = o.object_id
JOIN   sys.foreign_key_columns fkc  ON  fk.object_id = fkc.constraint_object_id
JOIN   sys.columns             c    ON  fkc.parent_object_id = c.object_id
                                AND fkc.parent_column_id = c.column_id
ORDER BY o.name

答案 3 :(得分:0)

不知道这是否更准确,但我在寻找类似https://encodo.com/latest/developer-blogs/create-indexes-for-all-foreign-keys-in-sql-server/时会发现这一点,该{{3}}会生成与上述某些脚本类似的create-script,这至少应该给最终在此使用的人提供更多选择尝试一下。

--  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
-- Executing this script will generate a create-script for inserting indexes
-- over all tables in the database.
 --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  -- 
Select
'IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N''[dbo].['
+ tab.[name]
+ ']'') AND name = N''IX_'
+ cols.[name]
+ ''') '
+ 'CREATE NONCLUSTERED INDEX [IX_'
+ cols.[name]
+ '] ON [dbo].['
+ tab.[name]
+ ']( ['
+ cols.[name]
+ '] ASC ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]'
From sys.foreign_keys keys
Inner Join sys.foreign_key_columns keyCols
 On keys.object_id = keyCols.constraint_object_id
Inner Join sys.columns cols
 On keyCols.parent_object_id = cols.object_id
 And keyCols.parent_column_id = cols.column_id
Inner Join sys.tables tab
 On keyCols.parent_object_id = tab.object_id
Order by tab.[name], cols.[name]

答案 4 :(得分:0)

看到所有这些答案都很棒,但是我需要忽略那些已经具有索引的外键。为此,我借用了一些代码,并用此处的一些代码对其进行了修改。

此代码的主要部分实际上来自: Identify all non indexed foreign keys

SELECT 'CREATE NONCLUSTERED INDEX ndx_' + FK.Table_Name + '__' + FK.Column_Name 
   + ' ON [' + FK.Table_Name + '] (' + FK.Column_Name + ')'
FROM (    
SELECT 
   Object_Name(a.parent_object_id) AS Table_Name
   ,b.NAME AS Column_Name
FROM 
   sys.foreign_key_columns a
   ,sys.all_columns b
   ,sys.objects c
WHERE 
   a.parent_column_id = b.column_id
   AND a.parent_object_id = b.object_id
   AND b.object_id = c.object_id
   AND c.is_ms_shipped = 0
EXCEPT

SELECT 
   Object_name(a.Object_id)
   ,b.NAME
FROM 
   sys.index_columns a
   ,sys.all_columns b
   ,sys.objects c
WHERE 
   a.object_id = b.object_id
   AND a.key_ordinal = 1
   AND a.column_id = b.column_id
   AND a.object_id = c.object_id
   AND c.is_ms_shipped = 0
)  FK