有人告诉我,如果我将两个表作为外键,SQL Server 将在子表中创建类似于索引的东西。我很难相信这是真的,但找不到与此相关的太多内容。
我问这个的真正原因是因为我们在删除语句中遇到了一些非常缓慢的响应时间,该语句针对可能有 15 个相关表的表。我问过我们的数据库人员,他说如果字段上有外键,那么它就像一个索引。您对此有何经验?我应该在所有外键字段上添加索引还是它们只是不必要的开销?
外键是一个约束,是两个表之间的关系——与索引本身无关。
但众所周知的事实是,对属于任何外键关系的所有列进行索引是很有意义的,因为通过 FK 关系,您通常需要查找相关表并根据单个值或一系列值。
因此,对 FK 中涉及的任何列进行索引是很有意义的,但 FK 本身并不是索引。
查看 Kimberly Tripp 的优秀文章 "When did SQL Server stop putting indexes on Foreign Key columns?"。
哇,答案都在地图上。所以 Documentation 说:
FOREIGN KEY 约束是索引的候选者,因为:
使用相关表中的 FOREIGN KEY 约束检查对 PRIMARY KEY 约束的更改。
当来自相关表的数据通过将一个表的 FOREIGN KEY 约束中的列与另一表中的主键或唯一键列进行匹配来组合查询时,外键列通常用于连接条件。索引允许 Microsoft® SQL Server™ 2000 在外键表中快速查找相关数据。但是,创建此索引不是必需的。即使两个表之间没有定义 PRIMARY KEY 或 FOREIGN KEY 约束,也可以组合来自两个相关表的数据,但是两个表之间的外键关系表明这两个表已被优化为在使用键作为查询的查询中组合其标准。
所以看起来很清楚(尽管文档有点混乱)它实际上并没有创建索引。
不,外键字段没有隐式索引,否则微软为什么会说"Creating an index on a foreign key is often useful"。您的同事可能会将引用表中的外键字段与被引用表中的主键混淆 - 主键 do 创建一个隐式索引。
外键不创建索引。只有备用键约束(唯一)和主键约束创建索引。在 Oracle 和 SQL Server 中确实如此。
假设您有一张名为 orders 的大桌子和一张名为 customers 的小桌子。从订单到客户有一个外键。现在如果你删除一个客户,Sql Server 必须检查没有孤单;如果有,则会引发错误。
要检查是否有任何订单,Sql Server 必须搜索大订单表。现在如果有索引,搜索会很快;如果没有,搜索会很慢。
所以在这种情况下,缓慢的删除可以用没有索引来解释。特别是如果 Sql Server 必须搜索 15 个没有索引的大表。
PS 如果外键有 ON DELETE CASCADE,Sql Server 仍然要搜索订单表,但随后要删除所有引用已删除客户的订单。
SQL Server 会为主键自动创建索引,但不会为外键创建索引。为外键创建索引。这可能是值得的开销。
在 PostgeSql 中,如果您点击 \d tablename,您可以自己检查索引
您将看到已在具有主键和唯一约束的列上自动创建 btree 索引,但不会在具有外键的列上创建。
我认为这至少回答了你的postgres问题。
严格来说,外键与索引完全无关,是的。但是,正如我上面的发言者所指出的,创建一个来加速 FK 查找是有意义的。事实上,在 MySQL 中,如果您没有在 FK 声明中指定索引,引擎 (InnoDB) 会自动为您创建它。
这取决于。如果您不自己创建索引,则会在 MySQL 上创建索引:
MySQL 要求对外键列进行索引;如果创建具有外键约束但在给定列上没有索引的表,则会创建索引。
来源:https://dev.mysql.com/doc/refman/8.0/en/constraint-foreign-key.html
MySQL 5.6 也一样。
据我所知不是。外键只添加了一个约束,即子键中的值也可以在父列的某处表示。它并没有告诉数据库子键也需要被索引,只是受到约束。
我注意到指向 MSSQL 的 Entity Framework 6.1 确实会自动在外键上添加索引。
REFERENCES
定义的外键关系的引用端创建索引。它会自动为PRIMARY KEY
或UNIQUE
约束创建UNIQUE
索引,并要求外键关系的 referenced 端存在UNIQUE
索引,但不会自动执行任何操作对于 reference 端,尽管自己制作一个通常是个好主意。请参阅stackoverflow.com/questions/970562/…(books_id, users_id)
,如果您只搜索books_id
,则可能会被使用;或books_id
和users_id
。它将 NOT 但是如果您需要搜索 onlyusers_id