我是否需要在外键上创build索引?

我有一张桌子A和一张桌子B AB的主键B_ID有一个外键。

出于某种原因(我知道有合法的理由),当我将这两个表join到密钥中时,并没有使用索引。

我是否需要在A.B_ID上单独创build一个索引,或者是否需要外键的存在?

外键约束本身并不提供索引 – 必须(也应该)创build索引。

创build外键不会自动在A.B_ID上创build索引。 所以从查询性能的angular度来看,通常在A.B_ID上创build一个单独的索引是有意义的。

如果你删除了B中的行,你肯定希望将A.B_ID编入索引。 否则,每次从B删除一行时,Oracle必须对A执行全表扫描,以确保没有孤立的logging(取决于Oracle版本,可能还有其他locking影响,但这些影响会减less在最近的Oracle版本中)。

只是为了更多的信息:Oracle不会自动创build一个索引(因为它是为了唯一的约束),因为(a)不需要强制执行约束,(b)在某些情况下,你不需要一个。

然而, 大多数情况下,您将需要创build一个索引(实际上,在Oracle Apex中有一个“未索引的外键”报告)。

每当应用程序需要能够删除父表中的一行时,或者更新PK值(这很less见)时,如果没有索引存在,DML将会受到影响,因为它必须locking整个子表。

我通常select添加索引的情况是FK与定义列的域(例如状态码表)的“静态数据”表(其中,父表的更新和删除从未完成直接由应用程序。 但是,如果在列上添加索引给应用程序中的重要查询带来好处,那么索引仍然是一个好主意。

SQL Server从来没有将索引自动放到外键列上 – 查看Kim Tripp关于这个城市神话的背景和历史的优秀博客文章 。

但是,索引外键列通常是一个好主意 – 所以,我build议确保每个FK列都由一个索引进行备份; 不一定只在这一列上 – 也许可以在两列或三列上创build索引,FK列作为第一列。 取决于你的情况和你的数据。

出于性能的原因,应该创build一个索引。 用于主表上的删除操作(以检查您正在删除的logging未使用)以及通常涉及外键的联接中。 只有less数表(我不创build它们在日志中)可能不需要索引,但可能在这种情况下可能也不需要外键约束。

有一些数据库已经自动在外键上创build索引。 Jet引擎(Microsoft Access文件)Firebird MySQL

当然

SQL Server Oracle

才不是

至于任何与绩效有关的事情,都取决于许多因素,而且在极高的活动环境下没有银弹,因此维持一个指数可能是不可接受的。

这里最显着的是似乎是select性的:如果索引中的值将被高度复制,那么可以给出更好的性能来删除索引(如果可能)并允许表扫描。