【发布时间】:2016-11-23 09:59:09
【问题描述】:
我有一个表,其 ID 是“真正的主键”的哈希值。如果我错了,请纠正我,但我认为我在这个表中的插入非常慢,因为这个键上有聚集索引(插入 100 000 行需要几分钟)。 当我将 key 更改为非聚集索引时,我的印象是 innoDB 仍然秘密地聚集在它上面。
有没有一种简单的方法可以避免我的主键上的 mysql 集群,而无需定义自动增量主键?
【问题讨论】:
我有一个表,其 ID 是“真正的主键”的哈希值。如果我错了,请纠正我,但我认为我在这个表中的插入非常慢,因为这个键上有聚集索引(插入 100 000 行需要几分钟)。 当我将 key 更改为非聚集索引时,我的印象是 innoDB 仍然秘密地聚集在它上面。
有没有一种简单的方法可以避免我的主键上的 mysql 集群,而无需定义自动增量主键?
【问题讨论】:
InnoDB 必须有一个PRIMARY KEY。
PRIMARY KEY,无论AUTO_INCREMENT 与否。UNIQUE 键,但前提是所有列都不是NULLable。场景 1. 插入表必须找到所需主键所在的块。对于AUTO_INCREMENT 和上面的#3,这将是表中的“最后一个”块。这 100K 行将进入表“末尾”的大约 1000 个块中。
场景 2. 否则(非 AI,但显式 PK;或 UNIQUE),需要找到一个块(可能从磁盘读取),检查密钥是否为 dup,然后更新该块并标记以供以后重写到磁盘.
如果所有块都适合缓冲池,那么其中任何一个的速度基本相同。但是如果表太大而不能被缓存,那么场景 2 会变得很慢——事实上随着表的增长越来越慢。这是因为 I/O。 GUID、UUID、MD5 和其他哈希因遭受这种减速而臭名昭著。
另一个问题:事务完整性规定每个事务都会引发一些其他 I/O。你的 100K 插入 100K 事务吗? 1 笔交易?最好的办法是在每个事务中以 100 到 1000 行为一组进行批处理。
我希望这些原则能让你弄清楚你的情况。如果没有,请为您正在考虑的每个选项提供CREATE TABLE。然后我们可以讨论您的详细信息。还要提供SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; 和你有多少内存。
【讨论】: