通过自动增量字段使用 MySQL 分区,如何保证 INSERT/LOAD DATA 语句只访问指定的分区?



一般上下文

我希望能够在插入具有AUTO INCREMENT主键的非平衡RANGE分区MySQL表时判断我的插入是否导致MySQL以任何方式与我指定的分区以外的分区进行通信。这对于预算大规模数据加载的未来容量非常有用;有了这种保证,我可以更准确地预测将数据加载到数据库中的性能和硬件资源成本。

我正在使用MySQL 5.6。

具体背景

假设我在 MySQL (5.6( 中有下表:

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) */

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

问题

  • 如果我执行包含PARTITION子句的INSERT INTO foo (data) PARTITION (hot) VALUES ('abc')或等效的LOAD DATA语句,是否正在访问hot所选分区以外的任何分区?

  • 如何判断这些 DML 语句正在访问哪些分区?

我尝试过什么

关于分区选择的MySQL文档说:

替换和插入现在仅锁定那些具有行的分区 插入或更换。但是,如果生成了AUTO_INCREMENT值 对于任何分区列,所有分区都将被锁定。

此外,它说:

由 LOAD DATA 语句对分区表施加的锁不能 修剪。

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

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

根据文档,

对于插入行的语句,行为的不同之处在于,找不到合适的分区会导致语句失败。对于 INSERT 和 REPLACE 语句都是如此

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

错误代码:1748。发现与给定分区集不匹配的行

这包括某些行匹配而某些行不匹配的语句, 因此,您不能使用它来填充"热"并丢弃会进入"溢出"的行(因为整个查询将失败(。

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

最新更新