复合键VS主键+不唯一索引

时间:2016-04-29 13:53:41

标签: mysql database innodb database-indexes

这就是我所拥有的:

table content : cat_id product_id data1 data2 etc.
这些类别显然不是唯一的。 产品ID是独一无二的。

2 queries : 1 -- SELECT * WHERE cat_id = :cat - must be as quick as possible 2 -- SELECT * WHERE product_id = :prodId In second select, I can add : AND cat_id = :cat

什么效率更高?

  • 1 - cat_id上的索引(非唯一)(适用于选择1)
  • 2 - product_id上的主键(唯一 - >选择2的优秀)
  • 3 - product_id上的cat_id + PK上的索引(非唯一)(分别适用于1& 2)
  • 4 - 复合[cat_id + product_id]的唯一约束(适用于1& 2)
  • 5 - 与4相同,但将复合定义为PK
  • 6 - 复合(4或5)+单指数/ PK

有关信息,我将在每个类别和大量类别(比如3000)中拥有大约20种产品 - 并且(因为它在表中是独一无二的)一个产品只属于一个类别 - 事实上,这不是真的猫和产品,这是为了简单的解释;)

谢谢!

2 个答案:

答案 0 :(得分:5)

没有主键的数据库只有一半打扮,根据你的说法,product_id是主键的理想候选者,所以我们选择它。主键将在

中使用
SELECT * WHERE product_id = :prodId

and cat_id = :cat_id是否成为查询的一部分无关紧要,除非您有cat_ids个与product_id相关联的数千{。}}。

然后在cat_id上选择一个索引。这将用于

SELECT * WHERE cat_id = :cat

如果数据的基数良好,这将非常快。这意味着表中有cat_id的广泛分布。 cat_id的索引不会在第一个查询中使用。因此,您有两个不同的索引,并且可以预期两个查询都非常快。

[cat_id+product_id] != [product_id+cat_id]以来,在索引方面,如果只有一个复合索引,那么另一个将很慢。

例如,假设我们现在有一个复合索引(cat_id,product_id) 以下查询无法使用此索引。

 SELECT * FROM tablename WHERE product_id = :prodId

但这两个查询都可以使用(cat_id,product_id)索引

SELECT * FROM tablename WHERE cat_id = :cat_id and product_id = :prodId
SELECT * FROM tablename WHERE cat_id = :catId

总结一下。选择1和2.但是如果cat_id的数量很小或者每个product_id都有很多cat_ids,请选择4,但要确保主键也已到位。

答案 1 :(得分:1)

如果这些只是 两个查询:

SELECT * FROM tablename WHERE cat_id = :cat_id and product_id = :prodId
SELECT * FROM tablename WHERE cat_id = :cat_id

您还有其他方法可以确保product_idUNIQUE,那么您只需要

PRIMARY KEY(cat_id, product_id)

最适合 SELECTs

优于INDEX(cat_id),因为(1)辅助密钥必须使用PK查找完成工作,(2)所有cat行都相邻,从而更有效。

如果product_id实际上是AUTO_INCREMENT,则添加

INDEX(product_id)

不,您不需要说UNIQUE(除非您倾向于故意尝试插入重复的product_ids)。 AI要求的唯一内容是id首先出现在某个索引中,这样每当mysqld重新启动时它都可以相当于SELECT max(id)

无论表格大小如何,我的建议都适用。

WHERE中的子句顺序重要。

JOINs不要要求JOIN上的PRIMARY KEY比使用辅助键的效率稍高一些,这比非索引列更有效(但仍然可能)。