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节,“分区限制”。
在分区键中使用索引前缀的列不受支持。这意味着
CHAR
、VARCHAR
、BINARY
和VARBINARY
列可以在分区键中使用,只要它们不使用前缀;因为索引定义中必须指定前缀,BLOB
和TEXT
列类型的前缀不允许在分区键中使用。在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 “线性哈希分区”,了解这个算法及其含义。