外键是否提高了查询性能?

假设我有2个表,Products 和 ProductCategory。这两个表都有关系,并且这是查询。

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

当我创建执行计划时,表 ProductCategory 执行集群索引查找,这是预期的。但是对于表产品,它执行集群索引扫描,这使我怀疑。为什么 FK 不能帮助提高查询性能?

所以我必须在 Products 上创建索引。类别。当我再次创建执行计划时,两个表都执行索引查找。并且估计的子树成本大大降低。

我的问题是:

  1. 除了 FK 有助于解决关系约束之外,它还有其他用处吗? 它是否提高了查询性能?

  2. 我是否应该在所有表中的所有 FK 列上创建索引(比如 Products. Category oryId) ?

110221 次浏览

外键是参照完整性工具,不是性能工具。至少在 SQLServer 中,创建 FK 不会创建关联索引,您应该在所有 FK 字段上创建索引以提高查找时间。

外键是数据库管理系统的一个概念,用于确保数据库完整性。

任何性能方面的影响/改进都只针对正在使用的数据库技术,对于外键的用途来说是次要的。

在 SQLServer 中,最好确保所有外键上都至少有一个非聚集索引。

我希望这为你澄清事情,但请随时要求更多的细节。

外键可以提高(并损害)性能

  1. 如上所述: 外键提高性能

  2. 应始终为 FK 列创建索引以减少查找。 SQLServer 不会自动这样做。

剪辑

由于链接现在似乎是死的 (赞扬克里斯注意到),下面显示了为什么外键可以提高(和损害)性能的要点。

外键可以提高性能

外键约束提高了读取时的性能 数据,但同时它减慢了性能的时间 插入/修改/删除数据。

在读取查询时,优化器可以使用外键约束来 创建更有效的查询计划作为外键 约束是预先声明的规则。这通常涉及跳过 查询计划的一部分,因为例如,优化器可以看到 由于外键约束,不需要执行 计划中的特定部分。

您可以使用它来帮助提高查询的效率。它确实允许您重新构造 SQLServer 中的查询,以使用外部联接而不是内部联接,从而消除了必须检查列中是否存在 null 的 SQL 服务器的必要性。您不需要使用这个限定符,因为外键关系已经强化了这一点。

所以这个:

select p.ProductId, p.Name, c.CategoryId, c.Name AS Category
from Products p
inner join ProductCategories c on
p.CategoryId = c.CategoryId
where c.CategoryId = 1;

变成这样:

 SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM ProductCategories c
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId
WHERE c.CategoryId = 1;

在小型查询中,这不一定会带来巨大的性能,但是当表变大时,效率会更高。

您最好的性能赌注是在您经常使用的字段上使用索引。如果使用 SQLServer,则可以使用事件探查器分析特定数据库,并获取输出的文件,并使用优化向导接收关于索引放置位置的建议。我也喜欢使用分析器来清除长时间运行的存储过程,我有一个十大最坏的罪犯名单,我每周公布,让人们诚实: D。

我不太了解 SQL 服务器,但是对于 Oracle,使用外键列会降低数据加载的性能。这是因为数据库需要检查每次插入的数据完整性。是的,正如前面提到的,对外键列设置索引是一种很好的做法。

在表中添加外键不会提高性能,只是说如果你在 ProductCategory ories 表数据库中插入一条记录,将尝试查找外键列的值是否存在于 products 表的主键值中,这种查找操作每次在 ProductCategory 表中添加一个新条目时都会增加数据库的开销。 因此,通过添加外键不会提高数据库性能,但它会注意数据库的完整性。 是的,如果您使用外键检查完整性,而不是运行许多查询来检查程序中数据库中是否存在记录,那么它将提高 db 的性能。

从 SQLServer2008开始,外键通过影响数据库引擎选择优化查询的方式来影响性能。请参考以下文章中的“星型联接启发法”: https://technet.microsoft.com/en-us/library/2008.04.dwperformance.aspx

对于 MySQL 5.7,它绝对可以非常好地加速涉及多个连接的查询!

我使用“解释”来理解我的查询,发现我加入了4-5个表-其中根本没有使用键。我只是向这些表添加了一个外键,结果是减少了90% 的加载时间。使用 > 5的查询现在只需要500毫秒或更少的时间。

这是一个巨大的进步!

而且,正如其他人所提到的,您还获得了确保关系完整性的额外好处。

除此之外,确保参照完整性也有自己的性能优势。它具有二级效果,即确保具有外键的表与外键的表是“最新的”。假设您有一个用户表和一个评论表,并且正在对评论表进行一些统计。也许如果你很难删除用户,你也不想再看到他们的评论。

是的,FK 可以加速 SELECT但减慢 INSERT/UPDATE/DELETE

SQLServer 使用 所有约束(包括 FK)为 SELECT构建更好的执行计划。

例如,如果您使用 Column1 = X运行一个查询,而 X不符合这个约束,那么服务器甚至不会碰到这个表。

另外,除非约束是在 “不可信”的状态中,但那是完全不同的情况。

附注。但是,除非您在这个列上有一个非聚集索引,否则使用外键(或其他约束)可以降低 INSERT/UPDATE/DELETE的速度