我被告知如果我将两个表外键,那么SQL Server将创建类似于子表中的索引的东西。我很难相信这是真的,但找不到与此有关的那些。
我提出这个问题的真正原因是因为我们在一个删除语句中遇到了一个非常慢的响应时间,这个表可能包含15个相关表。我问过我们的数据库人,他说如果字段上有外键,那么它就像一个索引。你有什么经历?我应该在所有外键字段上添加索引还是只是不必要的开销?
答案 0 :(得分:303)
外键是一个约束,两个表之间的关系 - 与索引本身无关。
但是已知的事实是,将所有列作为任何外键关系的一部分的索引很有意义,因为通过FK关系,您通常需要查找相关表并提取某些基于单个值或一系列值的行。
因此,对FK中涉及的任何列进行索引是很有意义的,但FK本身不是索引。
查看Kimberly Tripp的精彩文章"When did SQL Server stop putting indexes on Foreign Key columns?"。
答案 1 :(得分:39)
FOREIGN KEY约束是索引的候选者,因为:
使用相关表格中的FOREIGN KEY约束检查对PRIMARY KEY约束的更改。
当来自相关表的数据通过将一个表的FOREIGN KEY约束中的列与主键或唯一键列相匹配时,外键列通常用于连接条件中在另一张桌子上。索引允许Microsoft®SQLServer™2000快速查找外键表中的相关数据。但是,创建此索引不是必需的。即使表之间没有定义PRIMARY KEY或FOREIGN KEY约束,也可以组合来自两个相关表的数据,但是两个表之间的外键关系表明这两个表已被优化以组合在使用键的查询中它的标准。
所以看起来非常清楚(尽管文档有点混乱)它实际上并没有创建索引。
答案 2 :(得分:18)
不,外键字段没有隐式索引,否则微软为什么会说"Creating an index on a foreign key is often useful"。您的同事可能会将引用表中的外键字段与引用表中的主键混淆 - 主键执行创建隐式索引。
答案 3 :(得分:6)
SQL Server自动创建主键的索引,但不会为外键自动创建索引。为外键创建索引。这可能是值得的开销。
答案 4 :(得分:6)
假设您有一个名为orders的大表,以及一个名为customers的小表。从订单到客户有一个外键。现在,如果删除客户,Sql Server必须检查是否没有孤立订单;如果有,则会引发错误。
要检查是否有任何订单,Sql Server必须搜索大订单表。现在如果有索引,搜索速度会很快;如果没有,搜索将会很慢。
因此,在这种情况下,缓慢删除可以通过缺少索引来解释。特别是如果Sql Server必须搜索没有索引的15个大表。
P.S。如果外键具有ON DELETE CASCADE,则Sql Server仍然必须搜索订单表,然后删除任何引用已删除客户的订单。
答案 5 :(得分:4)
外键不会创建索引。只有备用键约束(UNIQUE)和主键约束才能创建索引。这在Oracle和SQL Server中都是如此。
答案 6 :(得分:3)
据我所知。外键仅添加一个约束,即子键中的值也可以在父列的某处表示。它并没有告诉数据库,子键也需要被索引,只能被约束。
答案 7 :(得分:3)
严格来说,外键与索引完全无关,是的。但是,正如我上面的发言者指出的那样,创建一个加速FK查找是有意义的。实际上,在MySQL中,如果你没有在FK声明中指定索引,引擎(InnoDB)会自动为你创建索引。
答案 8 :(得分:2)
在PostgeSql中,如果你点击\ d tablename
,你可以自己检查索引您将看到已在具有主键和唯一约束的列上自动创建btree索引,但不会在具有外键的列上创建。
我认为这至少可以为postgres回答你的问题。
答案 9 :(得分:2)
我注意到实体框架6.1指向MSSQL会自动在外键上添加索引。
答案 10 :(得分:1)
这取决于。在 MySQL 上,如果您不自己创建索引,则会创建索引:
<块引用>MySQL 要求对外键列进行索引;如果您创建的表具有外键约束但在给定列上没有索引,则会创建索引。
来源:https://dev.mysql.com/doc/refman/8.0/en/constraint-foreign-key.html
MySQL 5.6 也是如此。