本节讨论当前 MySQL 分区支持的限制与局限。This section discusses current restrictions and limitations on MySQL partitioning support.
禁止的构造。 分区表达式中不允许使用以下构造:Prohibited constructs. The following constructs are not permitted in partitioning expressions:
存储过程、存储函数、可加载函数或插件。Stored procedures, stored functions, loadable functions, or plugins.
声明变量或用户变量。Declared variables or user variables.
有关允许在分区表达式中使用的 SQL 函数列表,请参见 第 26.6.3 节,“分区与函数有关的限制”。For a list of SQL functions which are permitted in partitioning expressions, see Section 26.6.3, “Partitioning Limitations Relating to Functions”.
算术和逻辑运算符。 在分区表达式中可以使用算术运算符 +、- 和 *。然而,结果必须是整数值或 NULL(在 [LINEAR] KEY 分区情况下除外,本章其他部分有详细讨论;有关更多信息,请参见 第 26.2 节,“分区类型”)。Arithmetic and logical operators.
Use of the arithmetic operators
+,
-, and
* is permitted in
partitioning expressions. However, the result must be an integer
value or NULL (except in the case of
[LINEAR] KEY partitioning, as discussed
elsewhere in this chapter; see
Section 26.2, “Partitioning Types”, for more information).
DIV 运算符也被支持;/ 运算符不允许使用。The DIV operator is also supported;
the / operator is
not permitted.
位运算符 |、&、^、<<、>> 和 ~ 在分区表达式中不允许使用。The bit operators
|,
&,
^,
<<,
>>, and
~ are not
permitted in partitioning expressions.
服务器 SQL 模式。 使用用户定义分区的表不会保留其创建时生效的 SQL 模式。正如本手册其他地方所讨论的(参见 第 7.1.11 节,“服务器 SQL 模式”),许多 MySQL 函数和操作符的结果可能会根据服务器 SQL 模式而变化。因此,在创建分区表之后的任何时间更改 SQL 模式都可能导致这些表的行为发生重大变化,并且很容易导致数据损坏或丢失。基于这些原因,强烈建议在创建分区表之后不要更改服务器 SQL 模式。Server SQL mode. Tables employing user-defined partitioning do not preserve the SQL mode in effect at the time that they were created. As discussed elsewhere in this Manual (see Section 7.1.11, “Server SQL Modes”), the results of many MySQL functions and operators may change according to the server SQL mode. Therefore, a change in the SQL mode at any time after the creation of partitioned tables may lead to major changes in the behavior of such tables, and could easily lead to corruption or loss of data. For these reasons, it is strongly recommended that you never change the server SQL mode after creating partitioned tables.
对于服务器 SQL 模式中的一个变化导致分区表无法使用的情况,请考虑以下 CREATE TABLE 语句,只有在 NO_UNSIGNED_SUBTRACTION 模式生效时才能成功执行:For one such change in the server SQL mode making a partitioned
tables unusable, consider the following
CREATE TABLE statement, which can
be executed successfully only if the
NO_UNSIGNED_SUBTRACTION mode is
in effect:
mysql>SELECT @@sql_mode;+------------+ | @@sql_mode | +------------+ | | +------------+ 1 row in set (0.00 sec) mysql>CREATE TABLE tu (c1 BIGINT UNSIGNED)->PARTITION BY RANGE(c1 - 10) (->PARTITION p0 VALUES LESS THAN (-5),->PARTITION p1 VALUES LESS THAN (0),->PARTITION p2 VALUES LESS THAN (5),->PARTITION p3 VALUES LESS THAN (10),->PARTITION p4 VALUES LESS THAN (MAXVALUE)->);ERROR 1563 (HY000): Partition constant is out of partition function domain mysql>SET sql_mode='NO_UNSIGNED_SUBTRACTION';Query OK, 0 rows affected (0.00 sec) mysql>SELECT @@sql_mode;+-------------------------+ | @@sql_mode | +-------------------------+ | NO_UNSIGNED_SUBTRACTION | +-------------------------+ 1 row in set (0.00 sec) mysql>CREATE TABLE tu (c1 BIGINT UNSIGNED)->PARTITION BY RANGE(c1 - 10) (->PARTITION p0 VALUES LESS THAN (-5),->PARTITION p1 VALUES LESS THAN (0),->PARTITION p2 VALUES LESS THAN (5),->PARTITION p3 VALUES LESS THAN (10),->PARTITION p4 VALUES LESS THAN (MAXVALUE)->);Query OK, 0 rows affected (0.05 sec)
如果在创建 tu 后移除 NO_UNSIGNED_SUBTRACTION 服务器 SQL 模式,你可能将无法再访问此表:If you remove the
NO_UNSIGNED_SUBTRACTION server
SQL mode after creating tu, you may no longer
be able to access this table:
mysql>SET sql_mode='';Query OK, 0 rows affected (0.00 sec) mysql>SELECT * FROM tu;ERROR 1563 (HY000): Partition constant is out of partition function domain mysql>INSERT INTO tu VALUES (20);ERROR 1563 (HY000): Partition constant is out of partition function domain
另请参见 第 7.1.11 节,“服务器 SQL 模式”。See also Section 7.1.11, “Server SQL Modes”.
服务器 SQL 模式也会影响分区表的复制。源服务器和副本服务器的 SQL 模式不一致可能导致分区表达式的计算结果不同;这可能导致源服务器和副本服务器的表中数据在分区之间的分布不同,甚至可能导致在源服务器上成功的分区表插入操作在副本服务器上失败。为了获得最佳效果,您应始终在源服务器和副本服务器上使用相同的服务器 SQL 模式。Server SQL modes also impact replication of partitioned tables. Disparate SQL modes on source and replica can lead to partitioning expressions being evaluated differently; this can cause the distribution of data among partitions to be different in the source's and replica's copies of a given table, and may even cause inserts into partitioned tables that succeed on the source to fail on the replica. For best results, you should always use the same server SQL mode on the source and on the replica.
性能考虑。 分区操作对性能的一些影响如下所示:Performance considerations. Some effects of partitioning operations on performance are given in the following list:
文件系统操作。 分区和重新分区操作(例如
ALTER TABLE使用PARTITION BY ...,REORGANIZE PARTITION或REMOVE PARTITIONING)依赖于文件系统操作来实现。这意味着这些操作的速度会受到文件系统类型和特性、磁盘速度、交换空间、操作系统的文件处理效率以及与文件处理相关的 MySQL 服务器选项和变量等因素的影响。特别是,你应该确保large_files_support已启用,并且open_files_limit已正确设置。涉及InnoDB表的分区和重新分区操作可以通过启用innodb_file_per_table来提高效率。File system operations. Partitioning and repartitioning operations (such asALTER TABLEwithPARTITION BY ...,REORGANIZE PARTITION, orREMOVE PARTITIONING) depend on file system operations for their implementation. This means that the speed of these operations is affected by such factors as file system type and characteristics, disk speed, swap space, file handling efficiency of the operating system, and MySQL server options and variables that relate to file handling. In particular, you should make sure thatlarge_files_supportis enabled and thatopen_files_limitis set properly. Partitioning and repartitioning operations involvingInnoDBtables may be made more efficient by enablinginnodb_file_per_table.另请参见 最大分区数。See also Maximum number of partitions.
表锁。 通常,对表执行分区操作的进程会对该表加写锁。来自这些表的读取操作受影响较小;待处理的
INSERT和UPDATE操作会在分区操作完成后立即执行。有关InnoDB特定的此限制的例外,请参见 分区操作。Table locks. Generally, the process executing a partitioning operation on a table takes a write lock on the table. Reads from such tables are relatively unaffected; pendingINSERTandUPDATEoperations are performed as soon as the partitioning operation has completed. ForInnoDB-specific exceptions to this limitation, see Partitioning Operations.索引;分区裁剪。 与非分区表一样,合理使用索引可以显著加快分区表的查询速度。此外,设计分区表及其查询以利用分区裁剪可以大大提高性能。更多信息请参见第 26.4 节,“分区裁剪”。Indexes; partition pruning. As with nonpartitioned tables, proper use of indexes can speed up queries on partitioned tables significantly. In addition, designing partitioned tables and queries on these tables to take advantage of partition pruning can improve performance dramatically. See Section 26.4, “Partition Pruning”, for more information.
分区表支持索引条件下推功能。详见第 10.2.1.6 节,“索引条件下推优化”。Index condition pushdown is supported for partitioned tables. See Section 10.2.1.6, “Index Condition Pushdown Optimization”.
使用 LOAD DATA 的性能。 在 MySQL 8.4 中,
LOAD DATA使用缓冲来提高性能。您应该注意,为了实现这一点,每个分区的缓冲区会使用 130 KB 的内存。Performance with LOAD DATA. In MySQL 8.4,LOAD DATAuses buffering to improve performance. You should be aware that the buffer uses 130 KB memory per partition to achieve this.
最大分区数。 对于未使用 NDB 存储引擎的给定表,最大可能的分区数为 8192。此数字包括子分区。Maximum number of partitions.
The maximum possible number of partitions for a given table not
using the NDB storage engine is
8192. This number includes subpartitions.
使用 NDB 存储引擎的表可定义的最大用户分区数量取决于所使用的 NDB Cluster 软件版本、数据节点数量及其他因素。有关更多信息,请参见 NDB 和用户定义分区。The maximum possible number of user-defined partitions for a table
using the NDB storage engine is
determined according to the version of the NDB Cluster software
being used, the number of data nodes, and other factors. See
NDB and user-defined partitioning,
for more information.
如果在创建具有大量分区(但少于最大值)的表时,遇到类似 Got error ... from storage engine: Out of resources when opening file 的错误信息,您可以尝试通过增加 open_files_limit 系统变量的值来解决此问题。不过,这取决于操作系统,在所有平台上可能不可行或不建议;有关更多信息,请参见 B.3.2.16 节,“文件未找到及类似错误”。在某些情况下,由于其他方面的考虑,使用大量(数百个)分区也可能不建议,因此使用更多分区并不自动意味着结果更好。If, when creating tables with a large number of partitions (but
less than the maximum), you encounter an error message such as
Got error ... from storage engine: Out of resources
when opening file, you may be able to address the
issue by increasing the value of the
open_files_limit system variable.
However, this is dependent on the operating system, and may not be
possible or advisable on all platforms; see
Section B.3.2.16, “File Not Found and Similar Errors”, for more information.
In some cases, using large numbers (hundreds) of partitions may
also not be advisable due to other concerns, so using more
partitions does not automatically lead to better results.
另请参见 文件系统操作。See also File system operations.
分区的 InnoDB 表不支持外键。 使用 InnoDB 存储引擎的分区表不支持外键。更具体地说,这意味着以下两个语句成立:Foreign keys not supported for partitioned InnoDB tables.
Partitioned tables using the InnoDB
storage engine do not support foreign keys. More specifically,
this means that the following two statements are true:
使用用户定义分区的
InnoDB表的定义中不得包含外键引用;其定义中包含外键引用的InnoDB表不得分区。No definition of anInnoDBtable employing user-defined partitioning may contain foreign key references; noInnoDBtable whose definition contains foreign key references may be partitioned.没有
InnoDB表定义可以包含对用户分区表的外键引用;没有用户定义分区的InnoDB表可以包含被外键引用的列。NoInnoDBtable definition may contain a foreign key reference to a user-partitioned table; noInnoDBtable with user-defined partitioning may contain columns referenced by foreign keys.
刚列出的这些限制的适用范围包括所有使用 InnoDB 存储引擎的表。CREATE
TABLE 和 ALTER TABLE 语句如果会导致表违反这些限制,则不允许执行。The scope of the restrictions just listed includes all tables that
use the InnoDB storage engine.
CREATE
TABLE and ALTER TABLE
statements that would result in tables violating these
restrictions are not allowed.
ALTER TABLE ... ORDER BY。 对分区表运行 ALTER TABLE ... ORDER BY
column 语句只会在每个分区内对行进行排序。ALTER TABLE ... ORDER BY.
An ALTER TABLE ... ORDER BY
statement run
against a partitioned table causes ordering of rows only within
each partition.column
ADD COLUMN ... ALGORITHM=INSTANT。 一旦在分区表上执行 ALTER TABLE ... ADD
COLUMN ... ALGORITHM=INSTANT,就无法再与此表交换分区。ADD COLUMN ... ALGORITHM=INSTANT.
Once you perform
ALTER TABLE ... ADD
COLUMN ... ALGORITHM=INSTANT on a partitioned table,
it is no longer possible to exchange partitions with this table.
修改主键对 REPLACE 语句的影响。 在某些情况下(参见 第 26.6.1 节,“分区键、主键和唯一键”)修改表的主键可能是可取的。请注意,如果您的应用程序使用 REPLACE 语句并进行此操作,这些语句的结果可能会发生巨大变化。有关更多信息和示例,请参见 第 15.2.12 节,“REPLACE 语句”。Effects on REPLACE statements by modification of primary keys.
It can be desirable in some cases (see
Section 26.6.1, “Partitioning Keys, Primary Keys, and Unique Keys”)
to modify a table's primary key. Be aware that, if your
application uses REPLACE
statements and you do this, the results of these statements can
be drastically altered. See Section 15.2.12, “REPLACE Statement”, for more
information and an example.
全文索引。 分区表不支持 FULLTEXT 索引或搜索。FULLTEXT indexes.
Partitioned tables do not support FULLTEXT
indexes or searches.
空间列。 具有空间数据类型的列,例如 POINT 或 GEOMETRY,不能用于分区表。Spatial columns.
Columns with spatial data types such as POINT
or GEOMETRY cannot be used in partitioned
tables.
临时表。 临时表不能进行分区。Temporary tables. Temporary tables cannot be partitioned.
日志表。 无法对日志表进行分区;对这样的表执行 ALTER
TABLE ... PARTITION BY ... 语句会出错。Log tables.
It is not possible to partition the log tables; an
ALTER
TABLE ... PARTITION BY ... statement on such a table
fails with an error.
分区键的数据类型。 分区键必须是整数列或解析为整数的表达式。不能使用包含 ENUM 列的表达式。列或表达式的值也可以为 NULL;请参阅 第 26.2.7 节,“MySQL 分区如何处理 NULL”。Data type of partitioning key.
A partitioning key must be either an integer column or an
expression that resolves to an integer. Expressions employing
ENUM columns cannot be used. The
column or expression value may also be NULL;
see Section 26.2.7, “How MySQL Partitioning Handles NULL”.
此限制有两个例外:There are two exceptions to this restriction:
当按 [
LINEAR]KEY分区时,可以使用除TEXT或BLOB之外的任何有效 MySQL 数据类型的列作为分区键,因为内部键哈希函数可以从这些类型生成正确的数据类型。例如,以下两个CREATE TABLE语句是有效的:When partitioning by [LINEAR]KEY, it is possible to use columns of any valid MySQL data type other thanTEXTorBLOBas partitioning keys, because the internal key-hashing functions produce the correct data type from these types. For example, the following twoCREATE TABLEstatements are valid:CREATE TABLE tkc (c1 CHAR) PARTITION BY KEY(c1) PARTITIONS 4; CREATE TABLE tke ( c1 ENUM('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet') ) PARTITION BY LINEAR KEY(c1) PARTITIONS 6;在按
RANGE COLUMNS或LIST COLUMNS进行分区时,可以使用字符串、DATE和DATETIME列。例如,以下每个CREATE TABLE语句都是有效的:When partitioning byRANGE COLUMNSorLIST COLUMNS, it is possible to use string,DATE, andDATETIMEcolumns. For example, each of the followingCREATE TABLEstatements is valid:CREATE TABLE rc (c1 INT, c2 DATE) PARTITION BY RANGE COLUMNS(c2) ( PARTITION p0 VALUES LESS THAN('1990-01-01'), PARTITION p1 VALUES LESS THAN('1995-01-01'), PARTITION p2 VALUES LESS THAN('2000-01-01'), PARTITION p3 VALUES LESS THAN('2005-01-01'), PARTITION p4 VALUES LESS THAN(MAXVALUE) ); CREATE TABLE lc (c1 INT, c2 CHAR(1)) PARTITION BY LIST COLUMNS(c2) ( PARTITION p0 VALUES IN('a', 'd', 'g', 'j', 'm', 'p', 's', 'v', 'y'), PARTITION p1 VALUES IN('b', 'e', 'h', 'k', 'n', 'q', 't', 'w', 'z'), PARTITION p2 VALUES IN('c', 'f', 'i', 'l', 'o', 'r', 'u', 'x', NULL) );
前面提到的例外情况不适用于 BLOB 或 TEXT 列类型。Neither of the preceding exceptions applies to
BLOB or
TEXT column types.
子查询。 分区键不能是子查询,即使该子查询解析为整数值或NULL。Subqueries.
A partitioning key may not be a subquery, even if that subquery
resolves to an integer value or NULL.
键分区不支持列索引前缀。 当创建一个按键分区的表时,分区键中的任何使用列前缀的列都不允许在表的分区函数中使用。考虑以下CREATE TABLE语句,它包含三个VARCHAR列,并且其主键使用所有三列,并为其中一列指定了前缀。该语句会被拒绝并显示错误,如下所示:Column index prefixes not supported for key partitioning.
When creating a table that is partitioned by key, any columns in
the partitioning key which use column prefixes are not allowed
in the table's partitioning function. Consider the
following CREATE TABLE statement,
which has three VARCHAR columns,
and whose primary key uses all three columns and specifies a
prefix for one of them. This statement is rejected with an
error, as shown here:
mysql>USE d;Database changed mysql>CREATE TABLE t1 (->a VARCHAR(10000),->b VARCHAR(25),->c VARCHAR(10),->PRIMARY KEY (a(10), b, c)->) PARTITION BY KEY() PARTITIONS 2;ERROR 6123 (HY000): Column 'd.t1.a' having prefix key part 'a(10)' in the PARTITION BY KEY() clause is not supported.
有关按键分区表的一般信息,请参见 第 26.2.5 节,“KEY 分区”。For general information about partitioning tables by key, see Section 26.2.5, “KEY Partitioning”.
子分区的问题。 子分区必须使用 HASH 或 KEY 分区。只有 RANGE 和 LIST 分区可以进行子分区;HASH 和 KEY 分区不能进行子分区。Issues with subpartitions.
Subpartitions must use HASH or
KEY partitioning. Only
RANGE and LIST partitions
may be subpartitioned; HASH and
KEY partitions cannot be subpartitioned.
SUBPARTITION BY KEY 要求明确指定子分区列,而不像 PARTITION BY KEY 那样可以省略(在省略的情况下,默认使用表的主键列)。考虑如下语句创建的表:
SUBPARTITION BY KEY requires that the
subpartitioning column or columns be specified explicitly, unlike
the case with PARTITION BY KEY, where it can be
omitted (in which case the table's primary key column is used
by default). Consider the table created by this statement:
CREATE TABLE ts (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30)
);
你可以使用如下语句创建一个具有相同列、按 KEY 分区的表:You can create a table having the same columns, partitioned by
KEY, using a statement such as this one:
CREATE TABLE ts (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30)
)
PARTITION BY KEY()
PARTITIONS 4;
前面的语句会被当作这样写的,使用表的主键列作为分区列:The previous statement is treated as though it had been written like this, with the table's primary key column used as the partitioning column:
CREATE TABLE ts (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30)
)
PARTITION BY KEY(id)
PARTITIONS 4;
然而,尝试使用默认列作为子分区列创建子分区表的以下语句会失败,必须指定列,语句才能成功,如下所示:However, the following statement that attempts to create a subpartitioned table using the default column as the subpartitioning column fails, and the column must be specified for the statement to succeed, as shown here:
mysql>CREATE TABLE ts (->id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,->name VARCHAR(30)->)->PARTITION BY RANGE(id)->SUBPARTITION BY KEY()->SUBPARTITIONS 4->(->PARTITION p0 VALUES LESS THAN (100),->PARTITION p1 VALUES LESS THAN (MAXVALUE)->);ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') mysql>CREATE TABLE ts (->id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,->name VARCHAR(30)->)->PARTITION BY RANGE(id)->SUBPARTITION BY KEY(id)->SUBPARTITIONS 4->(->PARTITION p0 VALUES LESS THAN (100),->PARTITION p1 VALUES LESS THAN (MAXVALUE)->);Query OK, 0 rows affected (0.07 sec)
这是一个已知问题(见 Bug #51470)。This is a known issue (see Bug #51470).
数据目录和索引目录选项。 表级的 DATA DIRECTORY 和 INDEX
DIRECTORY 选项会被忽略(参见 Bug #32091)。您可以在 InnoDB 表的单个分区或子分区中使用这些选项。DATA DIRECTORY 子句中指定的目录必须为 InnoDB 所知。更多信息,请参见 使用 DATA DIRECTORY 子句。DATA DIRECTORY and INDEX DIRECTORY options.
Table-level DATA DIRECTORY and INDEX
DIRECTORY options are ignored (see Bug #32091). You
can employ these options for individual partitions or
subpartitions of InnoDB tables. The
directory specified in a DATA DIRECTORY
clause must be known to InnoDB. For
more information, see
Using the DATA DIRECTORY Clause.
修复和重建分区表。 语句 CHECK TABLE、OPTIMIZE TABLE、ANALYZE TABLE 和 REPAIR TABLE 都支持用于分区表。Repairing and rebuilding partitioned tables.
The statements CHECK TABLE,
OPTIMIZE TABLE,
ANALYZE TABLE, and
REPAIR TABLE are supported for
partitioned tables.
此外,您可以使用 ALTER TABLE ... REBUILD
PARTITION 来重建分区表的一个或多个分区;ALTER TABLE ... REORGANIZE
PARTITION 也会导致分区被重建。有关这两个语句的更多信息,请参见 第 15.1.9 节,“ALTER TABLE 语句”。In addition, you can use ALTER TABLE ... REBUILD
PARTITION to rebuild one or more partitions of a
partitioned table; ALTER TABLE ... REORGANIZE
PARTITION also causes partitions to be rebuilt. See
Section 15.1.9, “ALTER TABLE Statement”, for more information about these
two statements.
ANALYZE、CHECK、OPTIMIZE、REPAIR 和 TRUNCATE 操作支持子分区。请参见 第 15.1.9.1 节,“ALTER TABLE 分区操作”。ANALYZE, CHECK,
OPTIMIZE, REPAIR, and
TRUNCATE operations are supported with
subpartitions. See
Section 15.1.9.1, “ALTER TABLE Partition Operations”.
分区和子分区的文件名分隔符。 表分区和子分区的文件名包含生成的分隔符,例如 #P# 和 #SP#。这些分隔符的字母大小写可能会有所不同,不应依赖其大小写。File name delimiters for partitions and subpartitions.
Table partition and subpartition file names include generated
delimiters such as #P# and
#SP#. The lettercase of such delimiters can
vary and should not be depended upon.