如果我unique
对字段进行约束,是否还需要在该字段上创建索引以获得可扩展的插入时间?或者这是为我完成的(即使它使用的索引不可公开访问?)
具体来说,我正在使用 Apache Derby 进行原型设计,尽管我可能会在不久的将来将它转移到 MySQL。我也希望 SQL 标准中可能有一些关于此的说明。
我永远不需要按这个字段搜索,所以我宁愿不做一个无用的索引。但我宁愿有一个无用的索引而不是O(n)
插入时间。
如果我unique
对字段进行约束,是否还需要在该字段上创建索引以获得可扩展的插入时间?或者这是为我完成的(即使它使用的索引不可公开访问?)
具体来说,我正在使用 Apache Derby 进行原型设计,尽管我可能会在不久的将来将它转移到 MySQL。我也希望 SQL 标准中可能有一些关于此的说明。
我永远不需要按这个字段搜索,所以我宁愿不做一个无用的索引。但我宁愿有一个无用的索引而不是O(n)
插入时间。
主键 >= 唯一 >= 索引 == 键
InnoDB 数据按 PK 排序。MyISAM PK 的作用与 UNIQUE 相同。
INSERT 必须为您拥有的每个索引(任何类型)添加一个“行”。这需要一些时间。(通常没有足够的时间来处理。)索引都以 BTree 格式存储。MyISAM BTree 块为 1KB;InnoDB 使用 16KB。
插入 InnoDB 会同时更新 PK 和数据。
插入 MyISAM 通常会将数据“附加”到 .MYD。另外,它会在 PK 中添加一行(如果有)。
INSERT 必须首先验证任何 PRIMARY 或 UNIQUE 键都没有重复键。这是通过使用索引来完成的。因此,为什么 UNIQUE 和 FOREIGN KEY CONSTRAINT 真正构建索引。这是 O(logN),但通常是 CPU,而不是 I/O,因为如果缓存有效。
- 编辑 -
我的原始答案(如下)可能对您根本没有用,因为它没有解决
unique
约束问题。正如其他人所说,这些约束通常使用隐含的唯一索引来实现。在特殊情况下,这可能不是真的(例如disable novalidate
,对于 Oracle)。问题可能是:是否可以在没有索引的情况下强制执行唯一性?一般来说,答案是否定的,尽管在某些情况下聚集索引意味着索引和表是同一个对象。
--结束编辑--
你说“我宁愿有一个无用的索引,也不愿有一个 O(n) 的插入时间。”,但一般数据库没有 O(n) 的插入时间。有两种情况需要考虑:
有或没有索引的普通表:
新行被转储在堆的顶部。RDBMS 可能只查看1 个块,因此不仅仅是 O(1),而是非常小的 O(1)。
如果表有索引,则将向每个索引添加一个指向该行的指针。这通常是一个 O(log(n)) 操作。
具有某种集群的表,例如Oracle的索引组织表或集群,或 SQL Server 的集群索引等:
新行插入到特定块中,这可能导致块分裂或溢出,但无论发生什么,它仍然是 O(log(n)) 或更好,由用于查找块的 b 树或类似结构引起。
以粗体回答问题:是的,使字段唯一确实会像主键一样索引它。事实上,我已经在另一个关于Primary Keys Have Its Own Name 的问题中讨论过这个问题,以将其与其他 Unique (Candidate) Keys 区分开来。
至于约束,会为您创建索引,以便设置约束范式。您应该能够删除重复的索引,甚至是 UNIQUE 键,只要您所做的约束不引用您个人在约束范式之外创建的其他 UNIQUE 键。
您可能永远不必搜索此字段,但 MySQL 肯定必须作为其路径来确定键的有效性并确定如何执行 ON DELETE CASCADE 和 ON UPDATE CASCADE 操作。
UNIQUE 索引只是保证表中每一行中元组(单子、对、三元组、...、n 元组等)的唯一性。
删除此类重复索引由您自行决定,前提是您不破坏您希望表具有的约束范式。