使用由 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
.
问题
如果我执行 INSERT INTO foo (data) PARTITION (hot) VALUES ('abc')
或包含 PARTITION
子句的等效 LOAD DATA
语句,除了选定的 hot
分区之外还有任何分区正在访问?
我如何判断那些 DML 语句正在访问哪些分区?
我试过的
关于分区选择的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" 类型,它确实只会列出您指定的分区。
一般上下文
我想知道,当插入非平衡 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
.
问题
如果我执行
INSERT INTO foo (data) PARTITION (hot) VALUES ('abc')
或包含PARTITION
子句的等效LOAD DATA
语句,除了选定的hot
分区之外还有任何分区正在访问?我如何判断那些 DML 语句正在访问哪些分区?
我试过的
关于分区选择的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" 类型,它确实只会列出您指定的分区。