MySQL分区/分区的限制和限制

第6章分区的限制和限制

本节讨论MySQL分区支持的当前限制和限制。

禁止结构。以下构造在分区表达式中是不允许的:

  • 存储过程、存储函数、udf或插件。

  • 声明变量或用户变量。

有关分区表达式中允许使用的SQL函数列表,请参见第6.3节“与函数有关的划分限制”

算术和逻辑运算符。算术运算符的使用+-,在分区表达式中允许。但是,结果必须是整数值或的情况除外(线性)的关键分区,如本章其他部分所述;看到第三章,分区类型,以获取更多资料)。

DIV还支持Operator;的/不允许操作人员。

位运算符|<<>>,在分区表达式中不允许。

Server SQL模式。使用用户定义分区的表不会保留创建时有效的SQL模式。如本手册其他部分所述Server SQL模式),许多MySQL函数和操作符的结果可能会根据服务器的SQL模式而改变。因此,在创建分区表之后的任何时间更改SQL模式都可能导致这些表的行为发生重大变化,并很容易导致数据损坏或丢失。由于这些原因,强烈建议您不要在创建分区表后更改服务器SQL模式

对于使分区表不可用的服务器SQL模式中的一个这样的更改,请考虑以下内容创建表语句,该语句只有在NO_UNSIGNED_SUBTRACTION模式生效:

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) ->);错误1563 (HY000):分区常量超出分区函数域mysql>设置sql_mode=' no_unsigned_minus ';查询OK, 0 rows affected (0.00 sec) mysql> SELECT @@sql_mode;+-------------------------+ | @@ sql_mode  | +-------------------------+ | NO_UNSIGNED_SUBTRACTION  | +-------------------------+ 1行组(0.00秒)mysql >创建表涂(c1 BIGINT无符号)- >分区的范围(c1 - 10) (p0 - >分区值小于(5),- - - - - - >分区p1值小于(0)- >分区p2值小于(5),- - - - - - >分区p3值小于(10),- - - - - - >分区p4值小于(执行)- >);查询OK, 0行受影响(0.05秒)

如果你移除NO_UNSIGNED_SUBTRACTION创建后的server SQL模式,您可能无法再访问此表:

设置sql_mode= ";查询OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM tu;错误1563 (HY000):分区常量是超出分区功能域mysql> INSERT INTO tu VALUES (20);错误1563 (HY000):分区常量超出了分区函数域

另请参阅Server SQL模式

Server SQL模式也会影响分区表的复制。源和副本上不同的SQL模式可能导致分区表达式的计算方式不同;这可能导致给定表的源副本和副本副本中分区之间的数据分布不同,甚至可能导致在源上成功的对分区表的插入在副本上失败。为了获得最佳效果,应该始终在源和副本上使用相同的服务器SQL模式。

性能考虑。下面列出了分区操作对性能的一些影响:

  • 文件系统操作。分区和重分区操作(例如ALTER TABLE除以…重组分区,或删除分区)的实现依赖于文件系统操作。这意味着这些操作的速度受到文件系统类型和特征、磁盘速度、交换空间、操作系统的文件处理效率以及与文件处理相关的MySQL服务器选项和变量等因素的影响。特别是,你应该确保large_files_support是启用的open_files_limit设置正确。分区和重分区操作涉及InnoDB可以通过启用使表更加高效innodb_file_per_table

    另请参阅最大分区数

  • 表锁。通常,在表上执行分区操作的进程会获得表上的写锁。从这些表读取的数据相对不受影响;等待插入而且更新分区操作完成后立即执行操作。为InnoDB-此限制的特定例外,请参见分区操作

  • 索引;分区修剪。与非分区表一样,正确使用索引可以显著提高对分区表的查询速度。此外,在这些表上设计分区表和查询分区修剪可以显著提高性能。看到第五章,分区修剪,以查询更多资料。

    分区表支持索引条件下推。看到索引条件下推优化

  • 负载数据的性能。在MySQL 8.0中,加载数据使用缓冲来提高性能。您应该知道,为了实现这一点,缓冲区每个分区使用130 KB内存。

最大分区数。方法不使用的给定表的最大可能分区数NDB存储引擎为8192。这个数字包括子分区。

类的表的用户定义分区的最大可能数量NDB存储引擎根据使用的NDB集群软件版本、数据节点数量等因素确定。看到NDB和自定义分区,以查询更多资料。

如果在创建具有大量分区(但小于最大分区)的表时,您会遇到这样的错误消息收到错误…from存储引擎:打开文件时资源不足,你可以通过增加的价值来解决这个问题open_files_limit系统变量。然而,这取决于操作系统,在所有平台上可能都不可行或不可取;看到文件未找到和类似错误,以查询更多资料。在某些情况下,由于其他考虑,使用大量(数百个)分区也不可取,因此使用更多的分区并不会自动带来更好的结果。

另请参阅文件系统操作

分区InnoDB表不支持外键。的分区表InnoDB存储引擎不支持外键。更具体地说,这意味着以下两个表述是正确的:

  1. 没有定义InnoDB使用用户定义分区的表可能包含外键引用;没有InnoDB定义中包含外键引用的表可以分区。

  2. 没有InnoDB表定义可以包含对用户分区表的外键引用;没有InnoDB具有用户定义分区的表可能包含外键引用的列。

上面列出的限制范围包括所有使用InnoDB存储引擎。创建表而且ALTER TABLE不允许导致表违反这些限制的语句。

修改表…ORDER BY。一个修改表…命令对分区表运行的语句只会导致每个分区内的行排序。

修改主键对REPLACE语句的影响。在某些情况下,这是可取的第6.1节“分区键、主键和唯一键”)来修改表的主键。请注意,如果您的应用程序使用取代语句,你这样做,这些语句的结果可能会发生巨大的改变。看到替换语句,以获取更多信息和示例。

全文索引。分区表不支持全文索引或搜索。

空间列。具有空间数据类型的列,例如几何不能在分区表中使用。

临时表。临时表不能分区。

日志表。无法对日志表进行分区;一个修改表…除以…语句失败,并出现错误。

分区键的数据类型。分区键必须是整数列或解析为整数的表达式。表达式使用枚举不能使用列。列或表达式值也可以是;看到第3.7节,“MySQL分区如何处理NULL”

这个限制有两个例外:

  1. 当用[分割时线性关键,可以使用任何有效的MySQL数据类型的列,而不是文本作为分区键,因为内部键哈希函数从这些类型生成正确的数据类型。例如,下面两个创建表语句是有效的:

    创建表tkc (c1 CHAR)分区CREATE TABLE tke (c1 ENUM('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'))
  2. 当用范围列名单列,可以使用字符串,日期,DATETIME列。例如,以下每一种创建表声明有效:

    CREATE TABLE rc (c1 INT, c2 DATE) PARTITION BY RANGE COLUMNS(c2)(分区p0值小于('1990-01-01'),分区p1值小于('1995-01-01'),分区p2值小于('2000-01-01'),分区p3值小于('2005-01-01'),分区p4值小于(' MAXVALUE));创建表lc (INT c1, c2 CHAR(1)分区通过列表列(c2)(分区p0值(' a ', ' d ', ' g ', ' j ', ' m ', ' p ', ' s ', ' v ', ' y '),分区p1值(“b”、“e”、‘h’,‘k’,‘n’,‘问’,‘t’,‘w’,' z '),分区p2值(“c”,‘f’,‘我’,‘l’,‘o’,‘r’,‘你’,‘x’,NULL));

以上两种情况都不适用于文本列类型。

子查询。分区键可能不是子查询,即使该子查询解析为整数值或

键分区不支持列索引前缀。在创建按键分区的表时,分区键中使用列前缀的任何列都不会在表的分区函数中使用。考虑以下几点创建表语句,它有三个VARCHAR列,并且其主键使用所有三个列并为其中两个列指定前缀:

CREATE TABLE t1 (a VARCHAR(10000), b VARCHAR(25), c VARCHAR(10),主键(a(10), b, c(2)))

该语句被接受,但是结果表实际上是创建的,就像您发出了以下语句一样,只使用不包含前缀(列b)作为分区键:

CREATE TABLE t1 (a VARCHAR(10000), b VARCHAR(25), c VARCHAR(10),主键(a(10), b, c(2)))

在MySQL 8.0.21之前,如果发生了这种情况,就不会发出警告或任何其他指示,除非为分区键指定的所有列都使用了前缀,在这种情况下,语句失败了,但出现了误导性的错误消息,如下所示:

mysql> CREATE TABLE t2 (-> a VARCHAR(10000), -> b VARCHAR(25), -> c VARCHAR(10), -> PRIMARY KEY(a(10), b(5), c(2)) ->)一个主键必须包含表分区函数中的所有列

这在表演时也会发生ALTER TABLE或者在升级这些表时。

从MySQL 8.0.21开始,这种允许的行为已被弃用(在MySQL的未来版本中将被删除)。从MySQL 8.0.21开始,使用一个或多个在分区键中有前缀的列会对每个这样的列产生警告,如下所示:

mysql> CREATE TABLE t1 (-> a VARCHAR(10000), -> b VARCHAR(25), -> c VARCHAR(10), -> PRIMARY KEY(a(10), b, c(2)) ->)查询好,0行影响,2(1.25秒)mysql >显示警告警告\ G  *************************** 1。行  *************************** 级别:警告代码:1681信息:“test.t1列。'具有前缀键部分' A(10)'将被分区函数忽略。在PARTITION BY KEY()子句中使用带前缀的列已弃用,将在未来的版本中删除。*************************** 2。行***************************级别:警告代码:1681消息:列“test.t1.c”具有前缀键部分“c(2)”被分区函数忽略。在PARTITION BY KEY()子句中使用带前缀的列已弃用,将在未来的版本中删除。2行集合(0.00秒)

这包括在分区函数中使用的列被隐式定义为表主键中的列的情况按键分区()条款。

在MySQL 8.0.21及更高版本中,如果为分区键指定的所有列都使用前缀,则创建表使用的语句失败,并返回错误消息,正确地识别了问题:

mysql> CREATE TABLE t1 (-> a VARCHAR(10000), -> b VARCHAR(25), -> c VARCHAR(10), -> PRIMARY KEY(a(10), b(5), c(2)) -> PARTITION BY KEY()主键必须包含表分区函数中的所有列(不考虑带前缀的列)。

有关按键分区表的一般信息,请参见第3.5节,“键分区”

子分区问题。子分区必须使用哈希关键分区。只有范围而且列表分区可以是子分区;哈希而且关键分区不能进行子分区。

按键划分子分区要求显式指定子分区列,与按键分区,此处可以省略它(在这种情况下,默认使用表的主键列)。考虑以下语句创建的表:

CREATE TABLE ts (id INT NOT NULL AUTO_INCREMENT主键,名称VARCHAR(30))

您可以创建具有相同列的表,按关键,使用如下语句:

CREATE TABLE ts (id INT NOT NULL AUTO_INCREMENT主键,名称VARCHAR(30))

前面的语句被认为是这样写的,用表的主键列作为分区列:

CREATE TABLE ts (id INT NOT NULL AUTO_INCREMENT主键,名称VARCHAR(30))

但是,下面的语句试图使用默认列作为子分区列创建一个子分区表,但失败了,必须指定该列才能使语句成功,如下所示:

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) ->);错误1064(42000):你有一个错误的SQL语法;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) ->);查询OK, 0行受影响(0.07秒)

这是一个已知的问题(参见Bug #51470)。

数据目录和索引目录选项。表级数据目录而且索引目录选项被忽略(参见Bug #32091)。的单个分区或子分区可以使用这些选项InnoDB表。在MySQL 8.0.21中指定的目录数据目录从句必须是已知的InnoDB.有关更多信息,请参见使用DATA DIRECTORY子句

修复和重建分区表。的语句检查表优化表分析表,修理表对于分区表支持。

另外,还可以使用修改表…重建分区重建一个分区表的一个或多个分区;修改表…重组分区还会导致重新构建分区。看到ALTER TABLE语句,以了解有关这两种说法的更多信息。

分析检查优化修复,截断子分区支持操作。看到ALTER TABLE分区操作

分区和子分区的文件名分隔符。表分区和子分区文件名包括生成的分隔符,例如# P #而且# SP #.这些分隔符的字母大小写可以变化,不应依赖于它们。