73

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

数据库引擎是 SQL Server 2000

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

        )
4

3 回答 3

65

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

FOREIGN KEY 约束不必只链接到另一个表中的 PRIMARY KEY 约束;它也可以定义为引用另一个表中唯一约束的列。FOREIGN KEY 约束可以包含空值;但是,如果复合 FOREIGN KEY 约束的任何列包含空值,则会跳过对构成 FOREIGN KEY 约束的所有值的验证。要确保验证复合 FOREIGN KEY 约束的所有值,请在所有参与列上指定 NOT NULL。

于 2008-11-10T20:05:11.927 回答
22

当我阅读 Mike 的问题时,他在询问 FK 约束是否会在 FK 所在的表(表 1)中的 FK 列上创建索引。答案是否定的,而且一般来说。(出于约束的目的),没有必要这样做 另一方面,定义为约束的“目标”的列必须是引用表中的唯一索引,或者是主键或备用键。(唯一索引)或 Create Constraint 语句将失败。

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

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

于 2008-11-10T20:35:36.547 回答
8

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

  • 每次从引用(父)表中删除一条记录。
  • 每次这两个表在外键上连接。
  • 每次更新 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 上的索引的服务器开销将是不必要的。

于 2015-11-24T23:20:51.947 回答