外键是否在SQL Server中自动编入索引?

时间:2008-11-10 20:01:30

标签: sql-server indexing foreign-keys

以下SQL语句会自动在Table1.Table1Column上创建索引,还是必须显式创建索引?

数据库引擎是SQL Server 2000

       CREATE TABLE [Table1] (
. . .
            CONSTRAINT [FK_Table1_Table2] FOREIGN KEY 
            (
                [Table1Column]
            ) REFERENCES [Table2] (
                [Table2ID]
            )

        )

3 个答案:

答案 0 :(得分:60)

SQL Server不会自动在外键上创建索引。也来自MSDN:

  

FOREIGN KEY约束没有   仅链接到PRIMARY KEY   另一个表中的约束;它可以   也可以定义参考   UNIQUE约束的列   另一张桌子。一把外国钥匙   约束可以包含空值;   但是,如果是复合材料的任何列   FOREIGN KEY约束包含null   价值观,所有价值的验证   构成外键的   跳过约束。确保;确定   复合FOREIGN的所有值   验证KEY约束,指定   所有参与者都不是NULL   列。

答案 1 :(得分:23)

当我读到Mike的问题时,他正在询问FK约束是否会在FK所在的表中的FK列上创建索引(表1)。答案是否定的,一般而言。 (出于约束的目的),不需要这样做。另一方面,定义为约束的“TARGET”的列必须是引用表中的唯一索引,或者是主键或备用钥匙。 (唯一索引)或创建约束规则将失败。

(编辑:已添加以明确处理以下评论 - ) 具体而言,在提供外键约束所针对的数据一致性时。索引只会影响FK端行或行的删除,从而影响DRI约束的性能。使用约束时,在插入或更新期间,处理器知道FK值,并且必须检查PK侧上引用表中是否存在行。那里已有一个索引。删除PK端的行时,必须验证FK端没有行。在这种情况下,索引可能略有帮助。但这不是常见的情况。

除此之外,在某些类型的查询中,查询处理器需要在使用该外键列的连接的多个边上查找记录。当该外键上存在索引时,连接性能 增加。但是这种情况在连接查询中使用FK列是特殊的,而不是外键约束的存在......连接的另一侧是PK还是其他任意列并不重要。此外,如果您需要过滤或根据该FK列对查询结果进行排序,索引将有所帮助......同样,这与该列上的外键约束无关。

答案 2 :(得分:6)

不,在列上创建外键不会自动在该列上创建索引。未能索引外键列将导致在以下每种情况下进行表扫描:

  • 每次从引用的(父)表中删除记录。
  • 每次在外键上连接两个表。
  • 每次更新FK列。

在此示例模式中:

CREATE TABLE MasterOrder (
   MasterOrderID INT PRIMARY KEY)

CREATE TABLE OrderDetail(
   OrderDetailID INT,
   MasterOrderID INT  FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)

每次在MasterOrder表中删除记录时,都会扫描OrderDetail。每次加入OrderMaster和OrderDetail时,也会扫描整个OrderDetail表。

   SELECT ..
   FROM 
      MasterOrder ord
      LEFT JOIN OrderDetail det
       ON det.MasterOrderID = ord.MasterOrderID
   WHERE ord.OrderMasterID = @OrderMasterID

一般情况下,不对索引编制索引比规则更为例外。

不索引外键的情况是永远不会被利用的地方。这将使服务器维护它不必要的开销。类型表可能会不时属于此类别,例如:

CREATE TABLE CarType (
   CarTypeID INT PRIMARY KEY,
   CarTypeName VARCHAR(25)
)

INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')

CREATE TABLE CarInventory (
   CarInventoryID INT,
   CarTypeID INT  FOREIGN KEY REFERENCES CarType(CarTypeID)
)

假设CarType.CarTypeID字段永远不会被更新并且删除记录的一般假设几乎不会,如果从未通过CarTypeID搜索CarInventory,则不需要维护CarInventory.CarTypeID上的索引的服务器开销。 / p>