• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 列表分区

    MySQL中的列表分区在很多方面类似于范围分区。与按进行分区一样RANGE,必须明确定义每个分区。两种类型的分区之间的主要区别在于,在列表分区中,每个分区都是基于一组值列表中的一个而不是一组连续范围中的列值的成员资格来定义和选择的。价值观。这是通过使用where 是列值或基于列值的表达式并返回整数值,然后使用来定义每个分区的方法,其中where 是逗号分隔的整数列表。PARTITION BY LIST(expr)exprVALUES 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 NULL DEFAULT '1970-01-01',
        separated DATE NOT NULL DEFAULT '9999-12-31',
        job_code INT,
        store_id INT
    );
    

    (这是用作“ RANGE分区”中的示例的基础的表格。与其他分区示例一样,我们假定default_storage_engineis为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 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)
    );
    

    这样可以轻松地在表中添加或删除与特定区域相关的员工记录。例如,假设西部地区的所有商店都卖给了另一家公司。在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分区的情况不同,没有诸如“; ”的“包罗万象”MAXVALUEPARTITION ... 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语句将多个行插入单个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 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 8.0还提供了对LIST COLUMNS分区的支持,这是LIST分区的一种变体,它使您可以将整数类型以外的其他类型的列用于分区列,并将多个列用作分区键。有关更多信息,请参见“列分区”。

    上篇:范围分区

    下篇:列分区