【问题标题】:How to index all foreign keys in MS SQL?如何索引 MS SQL 中的所有外键?
【发布时间】:2011-05-21 15:35:36
【问题描述】:

我们有包含许多表和外键的大型 MS SQL 数据库。由于性能的原因,我们需要索引表中的所有外键,并且我们试图避免手动进行。有没有办法让 MS SQL 自动或使用一些工具来完成?

使用的 MS SQL 服务器是 MS SQL Server 2008 R2。

非常感谢。

【问题讨论】:

  • 你可以在你的数据库中找到所有的外键,然后也许通过构造sql语句来编写一个过程来索引它们以避免手动操作。
  • 您确定要索引所有表中的所有 FK 列吗?我建议仅在表将有超过几百行时才这样做。否则,可能仍会进行扫描。
  • @Pavanred 是对的。要使用的代码很大程度上取决于您使用的 SQL Server 版本;发布那个,有人可能会发布一个例子。
  • 谢谢。它是 MS SQL Server 2008 R2。
  • 为所有 fk stackoverflow.com/questions/10735407/…生成索引

标签: sql-server indexing foreign-keys


【解决方案1】:

我会引导您不要尝试自动执行此操作,并鼓励您检查您的系统(Google 缺少索引 DMV(SQL 2005 或更高版本)以获得良好的开端)并改为创建适当的索引。如果您尝试自动执行此操作,您可能会引入以下问题:

  • 在低的列上创建索引 将消耗资源但从不使用的基数 (例如,查找的外键 具有少量可能值的表)

  • 引入书签查找是因为 您创建的索引可能有 受益于包括额外的 列。

我并不是说你的外键不应该被索引,只是应该在创建这些索引时考虑一下。

【讨论】:

  • 感谢您的建议。我们将审查所有用于索引的外键。如果有更多的外键需要索引怎么办?也许将它们全部编入索引然后删除不必要的索引会更容易?
【解决方案2】:

这将允许查找所有 FK 及其相关列。如果有这样的倾向,他们可以编写一个脚本来测试所涉及的表的基数并生成索引

Select rc.constraint_name, table_name,column_name 
from 
    information_schema.REFERENTIAL_CONSTRAINTS rc
    INNER JOIN information_schema.CONSTRAINT_COLUMN_USAGE usage
    on rc.constraint_name = usage.constraint_name

【讨论】:

    【解决方案3】:

    下面的脚本应该会有所帮助:

    declare @schemaName varchar(128)
    declare @tableName varchar(128)
    declare @columnName varchar(128)
    
    declare @refSchemaName varchar(128)
    declare @refTableName varchar(128)
    declare @refColumnName varchar(128)
    
    declare @sql nvarchar(max)
    set @sql = ''
    
    declare cur cursor for
    select sch.name as SchemaName, tab.name as TableName, col.name as ColumnName, ref_sch.name as RefSchemaName, ref_tab.name as RefTableName, ref_col.name as RefColumnName
    from sys.foreign_keys fk
    join sys.foreign_key_columns fkc on fkc.constraint_object_id = fk.object_id
    join sys.tables tab on tab.object_id = fkc.parent_object_id
    join sys.schemas sch on sch.schema_id = tab.schema_id
    join sys.columns col on fkc.parent_column_id = col.column_id and fkc.parent_object_id = col.object_id
    join sys.tables ref_tab on ref_tab.object_id = fkc.referenced_object_id
    join sys.schemas ref_sch on ref_sch.schema_id = ref_tab.schema_id
    join sys.columns ref_col on fkc.referenced_column_id = ref_col.column_id and fkc.referenced_object_id = ref_col.object_id
    
    open cur
    fetch next from cur into @schemaName, @tableName, @columnName, @refSchemaName, @refTableName, @refColumnName
    while @@FETCH_STATUS = 0
    begin
        set @sql = '
        if not exists (SELECT * FROM sys.indexes 
        WHERE name=''IX_' + @schemaName + @tableName + '_' + @columnName + ''' AND object_id = OBJECT_ID(''' + @schemaName + '.' + @tableName + ''')) 
        begin
            CREATE INDEX IX_' + @schemaName + @tableName + '_' + @columnName + ' ON [' + @schemaName + '].[' + @tableName + '] 
            ([' + @columnName + ']) WITH (FILLFACTOR = 80) 
        end'
        --print @sql
        exec sp_executesql @sql
        fetch next from cur into @schemaName, @tableName, @columnName, @refSchemaName, @refTableName, @refColumnName
    end
    
    close cur
    deallocate cur
    

    选择所有外键后,它会创建名称格式为“IX_”schemaName““tableName”_“columnName”和fillfactor = 80 的索引。

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 2010-10-03
      • 2010-11-27
      • 1970-01-01
      • 2011-05-25
      相关资源
      最近更新 更多