本节提供了MySQL 8.3中分区的概念概述。
有关分区限制和功能限制的信息,请参阅第26.6节,“分区限制和限制”。
SQL标准没有提供太多关于数据存储物理方面的指导。SQL语言本身旨在独立于任何数据结构或媒体,schemas、表、行或列。然而,大多数高级数据库管理系统已经演化出一些方法来确定特定数据的物理存储位置,以文件系统、硬件或两者为基础。在MySQL中,InnoDB
存储引擎长期以来支持表空间的概念(见第17.6.3节,“表空间”),而MySQL Server,即使在引入分区之前,也可以配置为使用不同的物理目录来存储不同的数据库(见第10.12.2节,“使用符号链接”,以了解如何实现)。
分区将这个概念进一步扩展,使您能够根据需要将单个表的部分分布在文件系统中。实际上,表的不同部分将被存储为不同的表在不同的位置。用户选择的规则,根据需要将数据分配到不同的物理位置,称为分区函数,在MySQL中可以是模数、简单匹配、范围或值列表、内部哈希函数或线性哈希函数。该函数根据用户指定的分区类型进行选择,并将用户提供的表达式作为参数。该表达式可以是列值、函数作用于一个或多个列值,或者是一组一个或多个列值,具体取决于使用的分区类型。
在RANGE
、LIST
和[LINEAR
] HASH
分区中,分区列的值将被传递给分区函数,该函数将返回一个整数值,表示该记录应该存储在哪个分区中。该函数必须是非常量和非随机的。它不能包含任何查询,但可以使用一个有效的MySQL SQL表达式,只要该表达式返回NULL
或一个整数intval
,使得
-MAXVALUE <= intval <= MAXVALUE
(MAXVALUE
用于表示该整数类型的最小上限。-MAXVALUE
表示该整数类型的最大下限。)
对于[LINEAR
] KEY
、RANGE COLUMNS
和LIST COLUMNS
分区,分区表达式由一个或多个列组成。
对于[LINEAR
] KEY
分区,分区函数由MySQL提供。
有关允许的分区列类型和分区函数的更多信息,请参阅第26.2节,“分区类型”,以及第15.1.20节,“CREATE TABLE语句”,其中提供了分区语法描述和附加示例。有关分区函数限制的信息,请参阅第26.6.3节,“分区函数限制”。
这被称为水平分区,即表的不同行可能被分配到不同的物理分区。MySQL 8.3不支持垂直分区,即表的不同列被分配到不同的物理分区。目前没有计划引入垂直分区到MySQL中。
要创建分区表,您必须使用支持分区的存储引擎。在MySQL 8.3中,同一个分区表的所有分区必须使用相同的存储引擎。然而,没有什么可以阻止您在同一个MySQL服务器或同一个数据库中使用不同的存储引擎来创建不同的分区表。
在MySQL 8.3中,仅有InnoDB
和NDB
存储引擎支持分区。不能使用不支持分区的存储引擎,这些包括MyISAM
、MERGE
、CSV
和FEDERATED
存储引擎。
通过 KEY
或 LINEAR KEY
对表进行分区是可能的,使用 NDB
,但其他类型的用户定义分区不支持使用这个存储引擎。此外,使用这个存储引擎的表必须有一个明确的主键,并且任何在表的分区表达式中引用的列必须是主键的一部分。但是,如果在 PARTITION BY KEY
或 PARTITION BY LINEAR KEY
子句中没有列出列,则不需要主键。更多信息,请参见 第 25.2.7.1 节,“NDB 集群中的 SQL 语法不兼容”。
创建分区表时,默认存储引擎将被使用,就像创建任何其他表一样;要覆盖这个行为,只需要使用 [STORAGE] ENGINE
选项,就像对非分区表一样。目标存储引擎必须提供本机分区支持,否则语句将失败。您应该记住,[STORAGE] ENGINE
(和其他表选项)需要在 CREATE TABLE
语句中列出 before 任何分区选项。这是一个使用 InnoDB
存储引擎(无论 default_storage_engine
的值如何)创建分区表的示例:
CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE)
ENGINE=INNODB
PARTITION BY HASH( MONTH(tr_date) )
PARTITIONS 6;
每个 PARTITION
子句可以包括一个 [STORAGE] ENGINE
选项,但是在 MySQL 8.3 中这没有效果。
除非另有指定,以下讨论中的示例假设 default_storage_engine
是 InnoDB
。
分区适用于表的所有数据和索引;您不能只对数据或索引进行分区,也不能只对表的一部分进行分区。
每个分区的数据和索引可以使用 DATA DIRECTORY
和 INDEX DIRECTORY
选项分配到特定的目录中,这些选项位于 CREATE TABLE
语句中。
只有 DATA DIRECTORY
选项支持 InnoDB
表的个体分区和子分区。指定的目录必须是 InnoDB
已知的目录。更多信息,请参见 使用 DATA DIRECTORY 子句。
表的所有唯一键,包括主键,必须包含所有在分区表达式中使用的列。这意味着,像这样创建的表不能被分区:
CREATE TABLE tnp (
id INT NOT NULL AUTO_INCREMENT,
ref BIGINT NOT NULL,
name VARCHAR(255),
PRIMARY KEY pk (id),
UNIQUE KEY uk (name)
);
因为键 pk
和 uk
没有公共列,因此没有可用于分区表达式的列。可能的解决方法包括将 name
列添加到表的主键中,将 id
列添加到 uk
中,或者简单地删除唯一键。请参见 第 26.6.1 节,“分区键、主键和唯一键”,以获取更多信息。
此外,MAX_ROWS
和 MIN_ROWS
可以用来确定每个分区中可以存储的最大和最小行数。请参见 第 26.3 节,“分区管理”,以获取更多关于这些选项的信息。
MAX_ROWS
选项也可以用于创建 NDB 集群表具有额外分区,从而允许哈希索引的更大存储。请参阅 DataMemory
数据节点配置参数的文档,以及 第 25.2.2 节,“NDB 集群节点、节点组、碎片副本和分区”,以获取更多信息。
分区的某些优点列举如下:
-
分区使得可以在一个表中存储比单个磁盘或文件系统分区更多的数据。
-
已经失去有用性的数据通常可以通过删除包含该数据的分区(或分区)来轻松删除。相反,添加新数据的过程在某些情况下可以通过添加一个或多个新分区来存储特定的数据。
-
某些查询可以由于数据满足特定的
WHERE
子句而被优化,因为这些数据只存储在一个或多个分区上,从而自动排除其他分区的搜索。这被称为 分区修剪。有关更多信息,请参阅 第 26.4 节,“分区修剪”。此外,MySQL 还支持查询的显式分区选择。例如,
SELECT * FROM t PARTITION (p0,p1) WHERE c < 5
只选择表t
中的分区p0
和p1
中满足WHERE
条件的行。在这种情况下,MySQL 不会检查表t
的其他分区;这可以大大加速查询速度,当您已经知道要检查哪个分区或分区时。分区选择也支持数据修改语句DELETE
、INSERT
、REPLACE
、UPDATE
和LOAD DATA
、LOAD XML
。请参阅这些语句的描述以获取更多信息和示例。