使用由 AUTO INCREMENT 字段进行的 MySQL 分区,我如何保证 INSERT/LOAD DATA 语句仅访问指定的分区?

Using MySQL partitioning by an AUTO INCREMENT field, how can I guarantee that INSERT/LOAD DATA statements are only accessing specified partitions?

一般上下文

我想知道,当插入非平衡 RANGE-partitioned MySQL tables 与 AUTO INCREMENT 主键时,我的插入是否是导致 MySQL 以任何方式与我指定的分区以外的分区进行通信。这对于规划未来大规模数据加载的容量很有用;有了这种保证,我可以更准确地预测将数据加载到数据库的性能和硬件资源成本。

我正在使用 MySQL 5.6.

具体上下文

假设我在 MySQL (5.6) 中有以下 table:

CREATE TABLE foo (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data` varchar(6) COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=9001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
/*!12345 PARTITION BY RANGE (id)
(PARTITION cold VALUES LESS THAN (8000) ENGINE = InnoDB,
 PARTITION hot VALUES LESS THAN (9000) ENGINE = InnoDB,
 PARTITION overflow VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */

假设 table 不是稀疏的:没有行被删除,所以 count(*) = max(id) = 9001.

问题

我试过的

关于分区选择的MySQL documentation说:

REPLACE and INSERT now lock only those partitions having rows to be inserted or replaced. However, if an AUTO_INCREMENT value is generated for any partitioning column then all partitions are locked.

此外,它说:

Locks imposed by LOAD DATA statements on partitioned tables cannot be pruned.

这些语句无助于阐明 DML 查询正在访问哪些分区明确指定分区

我试过 EXPLAIN PARTITIONS INSERT INTO foo ...,但输出的 partitions 列始终是 NULL

根据 documentation,

For statements that insert rows, the behavior differs in that failure to find a suitable partition causes the statement to fail. This is true for both INSERT and REPLACE statements

因此,当您尝试插入与指定分区不匹配的行时,您将收到

Error Code: 1748. Found a row not matching the given partition set

这包括某些行匹配而某些行不匹配的语句, 所以你不能用它来填充 "hot" 并丢弃将进入 "overflow" 的行(因为整个查询将失败)。

MySQL 5.6 的 explain-otuput 不包含 insert 的单独行; partition 的值与您插入的数据源相关(在您使用 insert ... select ... partition ... 的情况下),即使您使用 values()(然后您使用 "no table",相关分区只是 null)。对于 MySQL 5.7+,有一个 "insert" 类型,它确实只会列出您指定的分区。