22.2.2 LIST 分区

MySQL 中的列 table 分区在很多方面类似于范围分区。与按RANGE进行分区一样,必须明确定义每个分区。两种类型的分区之间的主要区别在于,在列 table 分区中,每个分区是基于一组值列 table 中的一个而不是一组连续范围的列值中的列值的成员资格来定义和选择的。价值观。这是通过使用PARTITION BY LIST(expr)完成的,其中* expr 是列值或基于列值的 table 达式,然后返回整数值,然后通过VALUES IN (value_list)定义每个分区,其中 value_list *是逗号分隔的列 table 整数。

Note

在 MySQL 5.7 中,通过LIST进行分区时,可能仅与整数列 table 匹配(并且可能与NULL-参见第 22.2.7 节“ MySQL 分区如何处理 NULL”)匹配。

但是,在采用LIST COLUMN分区时,其他列类型也可以在值列 table 中使用,这将在本节后面介绍。

与通过范围定义分区的情况不同,列 table 分区不需要以任何特定 Sequences 声明。有关语法的详细信息,请参见第 13.1.18 节“ CREATE TABLE 语句”

对于以下示例,我们假设要分区的 table 的基本定义由此处显示的CREATE TABLE语句提供:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
);

(这是用作第 22.2.1 节“ RANGE 分区”中示例的基础的 table。)

假设有 20 个视频 Store 分布在 4 个专营权中,如下 table 所示。

RegionStore 编号
North3, 5, 6, 9, 17
East1, 2, 10, 11, 19, 20
West4, 12, 13, 14, 18
Central7, 8, 15, 16

要将 table 分区,以使属于同一区域的 Store 的行存储在同一分区中,可以使用此处显示的CREATE TABLE语句:

CREATE TABLE employees (
    id INT NOT NULL,
    fname VARCHAR(30),
    lname VARCHAR(30),
    hired DATE NOT NULL DEFAULT '1970-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT,
    store_id INT
)
PARTITION BY LIST(store_id) (
    PARTITION pNorth VALUES IN (3,5,6,9,17),
    PARTITION pEast VALUES IN (1,2,10,11,19,20),
    PARTITION pWest VALUES IN (4,12,13,14,18),
    PARTITION pCentral VALUES IN (7,8,15,16)
);

这样可以轻松地在 table 中添加或删除与特定区域相关的员工记录。例如,假设西部 locale 的所有 Store 都出售给另一家公司。在 MySQL 5.7 中,可以使用查询ALTER TABLE employees TRUNCATE PARTITION pWest删除与在该区域的 Store 工作的员工有关的所有行,该查询比等效的DELETE语句DELETE FROM employees WHERE store_id IN (4,12,13,14,18);可以更有效地执行。 (使用ALTER TABLE employees DROP PARTITION pWest还将删除所有这些行,但也会从 table 的定义中删除分区pWest;您将需要使用ALTER TABLE ... ADD PARTITION语句来恢复 table 的原始分区方案.)

RANGE分区一样,可以将LIST分区与通过哈希或键进行的分区组合以产生复合分区(子分区)。参见第 22.2.6 节“子分区”

RANGE分区的情况不同,不存在MAXVALUE之类的“包罗万象”;分区 table 达式的所有期望值都应包含在PARTITION ... VALUES IN (...)子句中。包含不匹配的分区列值的INSERT语句失败,并显示错误,如下例所示:

mysql> CREATE TABLE h2 (
    ->   c1 INT,
    ->   c2 INT
    -> )
    -> PARTITION BY LIST(c1) (
    ->   PARTITION p0 VALUES IN (1, 4, 7),
    ->   PARTITION p1 VALUES IN (2, 5, 8)
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO h2 VALUES (3, 5);
ERROR 1525 (HY000): Table has no partition for value 3

当使用单个INSERT语句插入多行时,行为取决于 table 是否使用事务存储引擎。对于InnoDBtable,该语句被视为单个事务,因此任何不匹配的值的存在都会导致该语句完全失败,并且不插入任何行。对于使用诸如MyISAM之类的非事务性存储引擎的 table,将插入包含不匹配值的行之前的任何行,但不插入任何行。

您可以使用IGNORE关键字来导致忽略这种类型的错误。如果这样做,则不会插入包含不匹配分区列值的行,但是会插入任何具有匹配值*的行,并且不会报告错误:

mysql> TRUNCATE h2;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM h2;
Empty set (0.00 sec)

mysql> INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
Query OK, 3 rows affected (0.00 sec)
Records: 5  Duplicates: 2  Warnings: 0

mysql> SELECT * FROM h2;
+------+------+
| c1   | c2   |
+------+------+
|    7 |    5 |
|    1 |    9 |
|    2 |    5 |
+------+------+
3 rows in set (0.00 sec)

MySQL 5.7 支持LIST COLUMNS分区。这是LIST分区的一种变体,它使您可以将整数类型以外的其他类型的列用于分区列,以及将多个列用作分区键。有关更多信息,请参见第 22.2.3.2 节“列 table 列分区”