我应该用整数主键替换我的 varchar 主键吗?

Nat*_*man 5 mysql innodb primary-key varchar

我有一个表,它有一个与“基本产品代码”相关联的 varchar 主键。它们很少更改,如果更改,通常只是被删除或添加。我认为最好为部分产品代码编制索引,以便我可以根据部分产品代码对数据执行搜索。

例如,“基本产品代码”采用以下格式:

ABC-AB12

该表存储了产品和配件之间的关系,每个产品或配件可以有多个关系:

Id          |     Prod     |    Acc    | Val
---------------------------------------------
ABC-AB12_1  |    ABC-AB12  |   ABC1    |  1
ABC-AB12_2  |    ABC-AB12  |   DEF1    |  2
ABC-AB12_3  |    ABC-AB12  |   GHI1    |  A
Run Code Online (Sandbox Code Playgroud)

我将每个关系的 id 存储为产品基本代码,并在其末尾附加一个整数。

我想如果我需要搜索特定产品的所有关系,使用主键和搜索会比在Prod列上搜索更快。

这是一个错误的假设吗?我应该将其Id改为自动递增的整数吗?

Rol*_*DBA 6

您应该有一个自动增量 PRIMARY KEY。由于我不知道表的存储引擎,我将尝试基于两者的答案。

数据库

一般来说,较小的主键总是比较大的更好。InnoDB 表的 PRIMARY KEY 存储在聚集索引中(在 InnoDB 中称为gen_clust_index)。由于InnoDB Page 是 16K,较小的键将使更多的键适合索引页。

应该注意的是,对于二级索引中的每个条目,都有一个主键。因此,较小的 PRIMARY KEY 不仅会使表受益,而且所有非唯一索引也会相应缩小。

我的ISAM

在密钥大小和索引方面,类似的原则适用于 MyISAM。此外,在您的特定情况下还有一个额外的好处,当涉及到 MyISAM 时并不经常讨论。

MyISAM 允许您为每个列值设置一个 auto_increment 键。我是什么意思?

查看您的问题中的表格,其中包含其他行:

Id          |     Prod     |    Acc    | Val
---------------------------------------------
ABC-AB12_1  |    ABC-AB12  |   ABC1    |  1
ABC-AB12_2  |    ABC-AB12  |   DEF1    |  2
ABC-AB12_3  |    ABC-AB12  |   GHI1    |  A
DEF-AB12_1  |    DEF-AB12  |   ABC1    |  1
DEF-AB12_2  |    DEF-AB12  |   DEF1    |  2
DEF-AB12_3  |    DEF-AB12  |   GHI1    |  A
GHI-AB12_1  |    GHI-AB12  |   ABC1    |  1
GHI-AB12_2  |    GHI-AB12  |   DEF1    |  2
GHI-AB12_3  |    GHI-AB12  |   GHI1    |  A
Run Code Online (Sandbox Code Playgroud)

你可以用 auoincrement 值替换 Id 并最终得到这个:

Id |     Prod     |    Acc    | Val
----------------------------------------------
1  |    ABC-AB12  |   ABC1    |  1
2  |    ABC-AB12  |   DEF1    |  2
3  |    ABC-AB12  |   GHI1    |  A
4  |    DEF-AB12  |   ABC1    |  1
5  |    DEF-AB12  |   DEF1    |  2
6  |    DEF-AB12  |   GHI1    |  A
7  |    GHI-AB12  |   ABC1    |  1
8  |    GHI-AB12  |   DEF1    |  2
9  |    GHI-AB12  |   GHI1    |  A
Run Code Online (Sandbox Code Playgroud)

如果Id看起来像这样,你会这样做:

PRIMARY KEY (Id)
Run Code Online (Sandbox Code Playgroud)

太好了。现在这是额外的好处:如果你让 PRIMARY KEY 看起来像这样:

PRIMARY KEY (Prod,Id)
Run Code Online (Sandbox Code Playgroud)

数据可以这样存储:

Id |     Prod     |    Acc    | Val
----------------------------------------------
1  |    ABC-AB12  |   ABC1    |  1
2  |    ABC-AB12  |   DEF1    |  2
3  |    ABC-AB12  |   GHI1    |  A
1  |    DEF-AB12  |   ABC1    |  1
2  |    DEF-AB12  |   DEF1    |  2
3  |    DEF-AB12  |   GHI1    |  A
1  |    GHI-AB12  |   ABC1    |  1
2  |    GHI-AB12  |   DEF1    |  2
3  |    GHI-AB12  |   GHI1    |  A
Run Code Online (Sandbox Code Playgroud)

这怎么可能?只有 MyISAM 存储引擎内置了这种机制!!!

我之前讨论过这个:

还有一件事:为什么有 PRIMARY KEY (Prod,Id)作为主键?这将允许您对每个产品 ID 进行排序。因此,您可以查找一种产品的序列 3 和另一种产品的序列 3。

结语

无论您决定采用哪种方式,使用较小的自动增量 PRIMARY KEY(4 字节)比使用较大的 PRIMARY KEY(超过 4 字节)对性能和磁盘空间更有意义。

试一试 !!!