MySQL 8.4 Reference Manual  /  ...  /  KEY Partitioning

26.2.5 键分区

通过键的分区与通过哈希的分区类似,除了哈希分区使用用户定义的表达式,而键分区使用MySQL服务器提供的哈希函数。NDB集群使用MD5()作为此目的;对于使用其他存储引擎的表,服务器使用其内部的哈希函数。

创建具有键分区的表的语法规则与创建使用哈希分区的表类似。主要差异如下:

  • KEY而不是HASH

  • KEY只接受零个或多个列名列表。用于分区键的任何列必须是表的主键的一部分,或者如果表有一个主键,则是整个主键。在没有指定分区键列的情况下,如果表有一个主键,那么该主键将被使用。例如,以下CREATE TABLE语句在MySQL 8.4中是有效的:

    CREATE TABLE k1 (
        id INT NOT NULL PRIMARY KEY,
        name VARCHAR(20)
    )
    PARTITION BY KEY()
    PARTITIONS 2;

    如果没有主键但有唯一键,则该唯一键将被用于分区键:

    CREATE TABLE k1 (
        id INT NOT NULL,
        name VARCHAR(20),
        UNIQUE KEY (id)
    )
    PARTITION BY KEY()
    PARTITIONS 2;

    然而,如果唯一键列未定义为NOT NULL,则前述语句将失败。

    在这两种情况下,分区键都是id列,即使它不出现在SHOW CREATE TABLE的输出中,也不在信息架构表PARTITIONS中的PARTITION_ EXPRESSION列中。

    与其他分区类型不同,用于键分区的列不受整数或NULL值的限制。例如,以下CREATE TABLE语句是有效的:

    CREATE TABLE tm1 (
        s1 CHAR(32) PRIMARY KEY
    )
    PARTITION BY KEY(s1)
    PARTITIONS 10;

    前述语句在指定不同的分区类型时将有效。(在这种情况下,简单地使用PARTITION BY KEY()也将有效且具有与PARTITION BY KEY(s1)相同的效果,因为s1是表的主键。)

    有关此问题的更多信息,请参阅第26.6节,“分区限制”

    在分区键中使用索引前缀的列不受支持。这意味着CHARVARCHARBINARYVARBINARY列可以在分区键中使用,只要它们不使用前缀;因为索引定义中必须指定前缀,BLOBTEXT列类型的前缀不允许在分区键中使用。在MySQL 8.4中,使用前缀的列在创建、更改或升级分区表时是被弃用的,服务器显示适当的警告或错误消息。有关更多信息和示例,请参阅键分区中不支持列索引前缀

    Note

    使用NDB存储引擎的表隐式地通过KEY分区,使用表的主键作为分区键(与其他MySQL存储引擎相同)。如果NDB集群表没有显式主键,则由NDB存储引擎为每个NDB集群表生成的“隐藏”主键用于分区键。

    如果您为一个NDB表定义了明确的分区方案,该表必须有明确的主键,并且在分区表达式中使用的任何列都必须是这个关键字的一部分。然而,如果表使用一个空分区表达式——也就是说,PARTITION BY KEY() 没有列引用——那么不需要明确的主键。

    您可以使用ndb_desc实用程序(带有-p选项)来观察这个分区。

    Important

    对于一个关键字分区的表,您不能执行ALTER TABLE DROP PRIMARY KEY,因为这样做会生成错误ERROR 1466 (HY000): 字段在字段列表中找不到。这不是对 NDB 集群表的问题,这些表是通过 KEY 分区的;在这种情况下,表会使用隐藏的主键作为新分区关键字重新组织。请参阅MySQL NDB 集群 8.4

还可以通过线性关键字来分区一个表。这里有一个简单的例子:

CREATE TABLE tk (
    col1 INT NOT NULL,
    col2 CHAR(5),
    col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS 3;

LINEAR 关键字对 KEY 分区和 HASH 分区具有相同的效果,分区号码是使用幂次方算法而不是模运算算法来派生。请参阅第26章 2.4.1 “线性哈希分区”,了解这个算法及其含义。