我已经阅读了许多关于取决于存储引擎的主键效率的文章,但我很困惑。
给定一个简单的多对多表,其中包含两个字段storeId
和zoneId
,以下哪种设计对 InnoDB 最有效,为什么?
CREATE TABLE store_zone(
storeId INT(10) UNSIGNED NOT NULL,
zoneId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY(storeId, zoneId)
);
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE store_zone(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
storeId INT(10) UNSIGNED NOT NULL,
zoneId INT(10) UNSIGNED NOT NULL,
PRIMARY KEY(id),
UNIQUE KEY(storeId, zoneId)
);
Run Code Online (Sandbox Code Playgroud)
笔记:
storeId
,我需要 ( , zoneId
) 对上的唯一键store
和zone
桌子,在这里没有显示可读性,所以在这两种情况下有上一个额外的要求指标zoneId
,以及既然我们在谈论 InnoDB,那么让我们将gen_clust_index
. 它是一个特殊的索引,它使 PRIMARY KEY 和关联的行数据可以从相同的 InnoDB 页面访问。
如果在表上定义 PRIMARY KEY,InnoDB 将使用它作为聚集索引。
如果你没有为你的表定义 PRIMARY KEY,MySQL 会选择第一个只有 NOT NULL 列的 UNIQUE 索引作为主键,InnoDB 使用它作为聚集索引。
如果 table 没有 PRIMARY KEY 或合适的 UNIQUE 索引,则 InnoDB 在包含行 ID 值的合成列上内部生成隐藏的聚集索引。行按 InnoDB 分配给此类表中行的 ID 排序。行 ID 是一个 6 字节的字段,随着插入新行而单调增加。因此,按行 ID 排序的行在物理上是按插入顺序排列的。
在这种情况下,您会真正感受到以下方面的效率或不足:
将单个 auto_increment 列作为PRIMARY KEY
使 PRIMARY KEY 的整体大小小于具有两列的大小。为什么?如果PRIMARY KEY
是两个 INT 而不是一个,那么 BTREE 页面将是两倍大。如果您使用外键约束和二级索引,这会变得更加痛苦,因为它们随后也必须在大小上爆炸。
在这种情况下,您将选择第二个架构以更好地使用索引。
将行数据插入具有两个 UNIQUE 索引的 InnoDB 表需要两倍的 BTREE 管理和唯一检查。
(storeId, zoneId)
)插入数百万行时,每个额外的 UNIQUE 索引的额外微秒会增加 CPU 时间。
在这种情况下,您将为更快的 INSERT 选择第一个模式。
磁盘空间和插入性能问题几乎迫使您做出选择。显然,您选择与哪一个一起生活。如果使用表示 的外键约束(storeId, zoneId)
,则需要使用 auto_increment 作为外部表中的引用的第二个模式。
归档时间: |
|
查看次数: |
1403 次 |
最近记录: |