你能在SQL中拥有多个密钥,为什么要这样?

时间:2011-06-17 02:09:52

标签: mysql sql key

您是否有理由想在TABLE中拥有多个KEY?在一个表中有多个KEY有什么意义?

以下是我发现的一个例子:

CREATE TABLE orders(
id INT UNSIGNED NOT NULL AUTO INCREMENT,
user_id INT UNSIGNED NOT NULL,
transaction_id VARCHAR(19) NOT NULL,
payment_status VARCHAR(15) NOT NULL,
payment_amount DECIMAL(15) NOT NULL,
payment_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id),
KEY(user_id),
)

另外,您会注意到DBase程序员没有transaction_id成为KEY。有这个原因吗?

5 个答案:

答案 0 :(得分:4)

有几个可能的原因。

  • 增强搜索性能(当WHERE子句使用KEY字段时,它执行得更快)
  • 限制表内容(当使用列的UNIQUE键时,它不能具有相同的值两次或更多)

这些是最常见的原因。

答案 1 :(得分:4)

MySQL中的

KEY是“索引”的替代语法 索引在数据库中很常见,但它们尚未涵盖ANSI - 它的纯粹奇迹就像它们一样相似。将一个以上的索引与表关联起来是很常见的 - 因为索引会以更新/删除/插入速度为代价来改进数据检索。

请注意,如果某个表的主键尚不存在,MySQL(5.x?)会自动创建索引。

答案 2 :(得分:3)

在SQL中,每个表可能只有一个PRIMARY KEY

KEY(foo)是标准SQL中的伪造语法。在MySQL KEY foo中,INDEX foo是一个命名不佳的同义词,并没有强制使用UNIQUE约束。 (名称很差,因为它实际上与密钥的功能无关。)

可能有多个UNIQUE INDICES可以扮演“候选键”的角色。 (可以在没有关联的INDEX的情况下指定唯一约束,但“键”的点通常是快速查找。)PRIMARY KEY的点是唯一标识单个记录,几乎完全由INDEX支持,甚至可能与数据的聚类直接相关。

只应使用确保数据有效性满足性能要求所需的最少量[唯一] INDICES - 它们也会对查询引擎造成性能损失因为有额外的更新和维护费用。

非唯一 INDEX(INDEX foo,或者在MySQL的情况下,KEY foo)纯粹是为了允许数据库优化查询。它们确实映射到“密钥”,可能被称为“覆盖索引”;如果由查询规划器选择,这些索引可以帮助提高性能,即使它们不向逻辑模型本身添加任何内容。 (出于性能原因,数据库引擎可能要求索引覆盖FOREIGN KEYS。)

在这种情况下,在user_id上创建一个INDEX(不认为“KEY”!)通常会(大大)加速查询,例如:

... WHERE user_id = {somenumber}

如果没有INDEX,上述查询将需要一个完整的表扫描(例如,读取所有记录)。

虽然我不知道为什么transaction_id没有成为索引,但可能不需要(甚至对给定的访问模式有害) - 考虑每个查询都需要快速:

  1. 不使用transaction_id或;
  2. 还有user_id = ...或其他可以使用INDEX的限制。也就是说,在类似WHERE user_id = ... AND transaction_id = ...的情况下,查询计划程序可能首先找到匹配用户的记录 ,然后查找匹配的transaction_id - 它仍然需要进行扫描,但只能在原始表的小得多的数据集上进行。只有普通的WHERE transaction_id = ...才需要进行全表扫描。
  3. 如果有疑问,请使用EXPLAIN - 或其他query analyzer - 并查看MySQL 认为应该做什么。作为最后一点,有时估计的查询执行计划可能与实际执行计划不同,过时的统计信息可以使查询计划程序选择一个非理想的计划。

    快乐的编码。

答案 3 :(得分:0)

“密钥”可能指代以下之一:

您可能需要多个,因为您需要在一个表中实现多个这些功能。这实际上很常见。

答案 4 :(得分:0)

在数据库理论中,关键是强制唯一性的约束。 relvar(类似于SQL表)可能确实具有多个候选键。一个典型的例子是化学元素的集合,其名称,符号,原子序数和原子量都是键(民间仍然希望为它添加自己的代理键;)

MySQL通过将KEY的同义词作为INDEX的同义词,继续滥用单词transaction_id。显然,MySQL表可能具有在给定情况下对性能所必需的索引数量。

从你的SQL DDL中可以清楚地看出,ID是一个代理键,所以我们必须寻找一个没有太多的自然键。虽然user_id可能是候选人,但订单可能涉及多个交易并不是不可想象的。实际上,我认为审核员会怀疑同一个用户同时发出的多个订单,因此建议payment_timetransaction_id的复合应该是关键。但是,如果transaction_id不是密钥,那么该表将不会完全规范化。因此,我会给设计师带来疑问,并假设{{1}}也是关键。