列表分区
MySQL中的列表分区在很多方面类似于范围分区。与按进行分区一样RANGE
,必须明确定义每个分区。两种类型的分区之间的主要区别在于,在列表分区中,每个分区都是基于一组值列表中的一个而不是一组连续范围中的列值的成员资格来定义和选择的。价值观。这是通过使用where 是列值或基于列值的表达式并返回整数值,然后使用来定义每个分区的方法,其中where 是逗号分隔的整数列表。PARTITION BY LIST(expr)
expr
VALUES IN(value_list)
value_list
注意在MySQL 8.0中,用by进行分区时,可能只与整数列表匹配(并且可能匹配
NULL
-参见“ MySQL分区如何处理NULL”)LIST
。但是,在使用
LIST COLUMN
分区时,其他列类型也可以在值列表中使用,这将在本节后面介绍。
与按范围定义分区的情况不同,列表分区不需要以任何特定顺序声明。有关语法的详细信息,请参见“ CREATE TABLE语句”。
对于下面的示例,我们假设要分区的表的基本定义由CREATE TABLE
此处所示的语句提供:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULLDEFAULT '1970-01-01', separated DATE NOT NULLDEFAULT '9999-12-31', job_code INT, store_id INT );
(这是用作“ RANGE分区”中的示例的基础的表格。与其他分区示例一样,我们假定default_storage_engine
is为InnoDB
。)
假设有20个视频商店分布在4个专营权中,如下表所示。
区域 | 商店编号 |
---|---|
北 | 3、5、6、9、17 |
东 | 1,2,10,11,19,20 |
西方 | 4、12、13、14、18 |
中央 | 7、8、15、16 |
要以某种方式对表进行分区,以便将属于同一区域的商店的行存储在同一分区中,可以使用以下CREATE TABLE
所示的语句:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULLDEFAULT '1970-01-01', separated DATE NOT NULLDEFAULT '9999-12-31', job_code INT, store_id INT )PARTITION BY LIST (store_id) (PARTITION pNorthVALUES IN (3,5,6,9,17),PARTITION pEastVALUES IN (1,2,10,11,19,20),PARTITION pWestVALUES IN (4,12,13,14,18),PARTITION pCentralVALUES IN (7,8,15,16) );
这样可以轻松地在表中添加或删除与特定区域相关的员工记录。例如,假设西部地区的所有商店都卖给了另一家公司。在MySQL 8.0中,可以使用查询删除与该区域内商店工作的员工相关的所有行,该查询的ALTER TABLE employees TRUNCATE PARTITION pWest
执行比等效DELETE
语句要有效得多DELETE FROM employees WHERE store_id IN(4,12,13,14,18);
。(使用ALTER TABLE employees DROP PARTITION pWest
还会删除所有这些行,但也会pWest
从表的定义中删除该分区;您将需要使用一条ALTER TABLE ... ADD PARTITION
语句来还原表的原始分区方案。)
与RANGE
分区一样,可以将LIST
分区与通过哈希或键进行分区组合以产生复合分区(子分区)。请参见“子分区”。
与RANGE
分区的情况不同,没有诸如“; ”的“包罗万象”MAXVALUE
。PARTITION ... VALUES IN(...)
子句中应包含分区表达式的所有期望值。INSERT
包含不匹配分区列值的语句失败,并显示错误,如下例所示:
mysql>CREATE TABLE h2 ( -> c1 INT, -> c2 INT -> ) ->PARTITION BY LIST (c1) ( ->PARTITION p0VALUES IN (1, 4, 7), ->PARTITION p1VALUES IN (2, 5, 8) -> ); Query OK, 0 rows affected (0.11 sec) mysql>INSERT INTO h2VALUES (3, 5); ERROR 1525 (HY000): Table has no partition for value 3
当使用单个INSERT
语句将多个行插入单个InnoDB
表时,InnoDB
该语句被视为单个事务,因此任何不匹配值的存在都会导致该语句完全失败,因此不会插入任何行。
您可以使用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 h2VALUES (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 8.0还提供了对LIST COLUMNS
分区的支持,这是LIST
分区的一种变体,它使您可以将整数类型以外的其他类型的列用于分区列,并将多个列用作分区键。有关更多信息,请参见“列分区”。