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

aw *_*rud 114 sql oracle indexing

我有一张桌子A和一张桌子B. 在主键上A有一个外键,.BBB_ID

由于某种原因(我知道有正当理由)当我在密钥上加入这两个表时它没有使用索引.

我是否需要单独创建索引A.B_ID或者是否存在外键提供的索引?

DCo*_*kie 128

仅外键约束不提供索引 - 必须(并且应该)创建索引.

  • 如果没有明确地引用特定的数据库实现,这个答案就毫无意义.当然这个问题被标记为"oracle",但是当你从谷歌搜索登陆这里时,这并不是很明显. (13认同)
  • 在某些数据库上创建外键约束也会创建索引...即Jet Engine(MSAccess文件,Firebird和MySQL) (8认同)
  • 我可以确认PostgreSQL - 至少在本文发布时 - 不会自动执行. (4认同)

Jus*_*ave 43

创建外键不会自动在A.B_ID上创建索引.因此,从查询性能角度来看,在A.B_ID上创建单独的索引通常是有意义的.

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

  • @Clamari - 如果C的主键为(A_ID,B_ID),则主键将负责从A中删除.如果您还希望能够有效地从B中删除,则需要索引` B_ID`. (3认同)

Jef*_*emp 23

更多信息:Oracle不会自动创建索引(就像它对唯一约束一样),因为(a)不需要强制执行约束,(b)在某些情况下,您不需要.

但是,大多数情况下,您需要创建一个索引(事实上,在Oracle Apex中有一个"未编制索引的外键"的报告).

每当应用程序需要能够删除父表中的行或更新PK值(这是罕见的)时,如果不存在索引,则DML将受到影响,因为它必须锁定整个子表.

我通常选择添加索引的情况是FK指向定义列的域的"静态数据"表(例如状态代码表),其中父表上的更新和删除永远不会完成直接由申请.但是,如果在列上添加索引可以为应用程序中的重要查询带来好处,那么索引仍然是个好主意.


mar*_*c_s 12

SQL Server从未将索引自动放入外键列 - 请查看Kim Tripp 关于这个都市神话的背景和历史的优秀博客文章.

但是,通常最好将外键列索引 - 所以是的,我建议确保每个FK列都由索引备份; 不一定只在那一列上 - 也许在两列或三列上创建索引是有意义的,其中FK列是第一列.取决于您的方案和数据.


bub*_*ubi 6

出于性能原因,应创建索引.用于主表上的删除操作(用于检查您正在删除的记录是否未使用)以及通常涉及外键的连接.只有少数表(我不在日志中创建它们)可能不需要索引,但可能在这种情况下,您可能也不需要外键约束.

有些数据库已经自动在外键上创建索引.Jet Engine(微软Access文件)Firebird MySQL

当然

SQL Server Oracle

才不是

  • 请注意,FIrebird SQL会自动执行此操作.这正是我想要的. (3认同)