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

时间:2009-02-03 14:03:28

标签: sql sql-server performance indexing foreign-keys

假设我有2个表,Products和ProductCategories。两个表都与CategoryId有关系。这是查询。

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;

当我创建执行计划时,表ProductCategories执行集群索引搜索,这是期望的。但对于表产品,它执行集群索引扫描,这让我怀疑。为什么FK无助于提高查询性能?

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

我的问题是:

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

  2. 我应该在所有表格中的所有FK列(喜欢的Products.CategoryId)上创建索引吗?

10 个答案:

答案 0 :(得分:172)

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

答案 1 :(得分:53)

外键可以改善(和伤害)性能

  1. 如上所述:Foreign keys boost performance

  2. 您应该始终在FK列上创建索引以减少查找。 SQL Server不会自动执行此操作。

  3. 修改

    由于链接现在似乎已经死了(感谢Chris注意到),下面显示了为什么外键可以改善(和伤害)性能的要点。

    Can Foreign key improve performance

      

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

         

    在读取查询的情况下,优化器可以使用外键约束   创建更高效​​的查询计划作为外键   约束是预先声明的规则。这通常涉及跳绳   查询计划的某些部分,因为例如优化器可以看到   因为外键约束,所以不必执行   该计划的特定部分。

答案 2 :(得分:13)

外键是用于确保数据库完整性的DBMS概念。

任何性能影响/改进都将特定于所使用的数据库技术,并且仅次于外键的目的。

在SQL Server中,最好确保所有外键至少具有非聚集索引。

我希望这能为您解决问题,但请随时提出更多详情。

答案 3 :(得分:4)

您最好的表现是在经常使用的字段上使用索引。如果使用SQL Server,则可以使用分析器来分析特定数据库,并使用输出的文件并使用调整向导来接收有关索引放置位置的建议。我也喜欢使用分析器来清除长时间运行的存储过程,我每周都会发布十大最糟糕的违规者列表,让人诚实:D。

答案 4 :(得分:3)

您可以使用它来帮助提高查询效率。它允许您重构SQL Server中的查询以使用外部联接而不是内部联接,从而删除sql server必须检查列中是否存在null。您不需要放置该限定符,因为外键关系已经为您强制执行。

所以这个:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere 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;

这不一定会在小型查询中产生巨大的性能,但是当表变大时,它可以更高效。

答案 5 :(得分:1)

我对SQL服务器知之甚少,但对于Oracle,拥有外键列会降低数据加载的性能。这是因为数据库需要检查每个插入的数据完整性。是的,正如已经提到的那样,在外键列上有一个索引是一个很好的做法。

答案 6 :(得分:1)

在表中添加外键不会提高性能,只是说如果在ProductCategories表数据库中插入记录,将尝试查找外键列的值,该值存在于products表的主键值中,查找,每次在ProductCategories表中添加新条目时,操作都会在数据库上产生开销。 因此,通过添加外键不会提高数据库性能,但会关注数据库的完整性。 是的,如果使用外键检查完整性而不是运行许多查询以检查程序中的数据库是否存在,那么它将提高数据库的性能。

答案 7 :(得分:1)

对于MySQL 5.7,它绝对可以加快涉及多个连接的查询速度!

我使用'explain'来理解我的查询,发现我加入了4-5个表 - 根本没有使用密钥。我什么都没做,只是在这些表中添加了一个外键,结果是加载时间减少了90%。花费> 5s的查询现在需要500毫秒或更少。

这是一个非常好的改进!

并且,正如其他人所提到的,您将获得确保关系完整性的额外奖励。

除此之外,确保参照完整性也有其自身的性能优势。它具有确保具有外键的表与外表一起“最新”的二阶效果。假设您有一个用户表和一个注释表,并且您正在对注释表进行一些统计。可能如果您难以删除用户,您也不再需要他们的评论了。

答案 8 :(得分:0)

从SQL Server 2008开始,外键可以通过影响数据库引擎选择优化查询的方式来影响性能。请参阅以下文章中的Star Join Heuristics:https://technet.microsoft.com/en-us/library/2008.04.dwperformance.aspx

答案 9 :(得分:0)

是的,FK 可以加速 ^([a-zA-Z]+)\/((?:\d{1,3}\.){3,4}\d{1,3})$ 但减慢 SELECT

SQL Server 使用所有约束(包括 FK)为 INSERT/UPDATE/DELETE 构建更好的执行计划。

例如,如果您使用 SELECT 运行查询并且 Column1 = X 不符合约束条件,则服务器甚至不会触及表。

附言除非约束在 "untrusted" state 中,但那是完全不同的故事。

P.P.S.但是,使用外键(或其他约束)会减慢 X 的速度,除非您在此列上有非聚集索引