26.1 MySQL分区概述
本节提供了MySQL 8.4中分区的概念性概述。
有关分区限制和特性限制的信息,请参阅第26.6节,“分区限制”。
SQL标准对数据存储的物理方面提供了很少的指导。SQL语言本身旨在独立于任何数据结构或媒体之下工作,用于操作模式、表格、行或列。然而,大多数高级数据库管理系统都发展了一些方法来确定特定数据应该存储在文件系统、硬件还是两者中哪个地方。在MySQL中,InnoDB
存储引擎长期以来就支持了表空间的概念(参见第17.6.3节,“表空间”),而MySQL服务器,即使在分区功能引入之前,也可以配置以使用不同的物理目录来存储不同数据库(参见第10.12.2节,“符号链接”,了解如何实现这一点)。
分区将这个概念推进了一步,让您能够根据需要设置的规则来分布表中的不同部分在文件系统中。实际上,表格的一部分被存储为不同的表格在不同的位置。用户选择的规则,即用于数据划分的规则,被称为分区函数,在MySQL中可以是模数、简单匹配一个值列表或范围集、内部哈希函数或线性哈希函数。根据用户指定的分区类型,该函数被选择,并且它的参数是由用户提供的表达式的值。这一表达式可以是一个列值、一些列值的函数,或根据使用的分区类型,一些或多个列值的集合。
对于RANGE
、LIST
和[LINEAR
] HASH
分区,分区函数接收分区列的值,该值代表应该将该记录存储在哪个分区中。这个函数必须是非恒定的且非随机的。它不能包含任何查询,但可以使用MySQL有效的SQL表达式,只要该表达式返回NULL
或一个整数intval
,使得
-MAXVALUE <= intval <= MAXVALUE
(对于表示所考虑整数类型中上界的最大值,-MAXVALUE表示下界。)
对于[LINEAR
] KEY
、RANGE COLUMNS
和LIST COLUMNS
分区,分区表达式由一组一个或多个列组成。
对于[LINEAR
] KEY
分区,MySQL提供了分区函数。
有关允许的分区列类型和分区函数的更多信息,请参阅第26.2节,“分区类型”,以及第15.1.20节,“CREATE TABLE语句”,它提供了分区语法描述和附加示例。有关分区函数限制的信息,请参阅第26.6.3节,“与函数相关的分区限制”。
这称为水平分区,即表格中不同行可能被分配到不同的物理分区。MySQL 8.4不支持垂直分区,在这种情况下,表格中的不同列被分配到不同的物理分区。目前,对MySQL进行垂直分区的计划尚未确定。
为了创建分区表,您必须使用支持它们的存储引擎。在MySQL 8.4中,每个分区表的所有分区都必须使用相同的存储引擎。然而,没有阻止您在同一个MySQL服务器或数据库中为不同的分区表使用不同存储引擎。
在MySQL 8.4中,支持分区的唯一存储引擎是InnoDB
和NDB
。对于不支持分区的存储引擎,包括MyISAM
、MERGE
、CSV
和FEDERATED
,分区是无法使用的。
使用NDB
存储引擎进行基于KEY
或LINEAR KEY
的分区是可能的,但其他类型的用户定义分区对于使用此存储引擎的表是不支持的。另外,一个使用用户定义分区的NDB
表必须有一个显式的主键,并且在表的分区表达式中引用列必须是主键的一部分。然而,如果在CREATE TABLE
或ALTER TABLE
用于创建或修改一个用户分区的NDB
表的语句中没有列出任何在PARTITION BY KEY
或PARTITION BY LINEAR KEY
子句中的列,那么该表不需要有一个显式的主键。有关更多信息,请参阅第25.2.7.1 节,“NDB 集群中 SQL 语法的非兼容性”
。
创建分区表时,默认使用的存储引擎与创建普通表时相同;要覆盖此行为,只需像对待未分区的表一样在CREATE TABLE
语句中使用[STORAGE] ENGINE
选项。目标存储引擎必须提供原生分区支持,否则语句将失败。你应该记住,在CREATE TABLE
语句中使用分区选项之前,你需要列出[STORAGE] ENGINE
(以及其他表选项)。以下是创建一个使用InnoDB
存储引擎并被哈希分区到6个分区的表的示例:
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.4中,这一点没有效果。
除非另有说明,以下讨论中的所有示例都假设default_storage_engine
是InnoDB
。
分区适用于表的所有数据和索引;你不能只对数据或索引进行分区,或者只对表的一部分进行分区。
每个分区的数据和索引可以被分配到特定的目录中,使用CREATE TABLE
用于创建分区表的语句中的DATA DIRECTORY
和INDEX DIRECTORY
选项。
对于InnoDB
表的单个分区和子分区,只支持DATA DIRECTORY
选项。指定在DATA DIRECTORY
子句中的目录必须是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集群节点、节点组、片段副本和分区”的更多信息,请参阅相关文档。
以下是分区的一些优点:
-
分区使得可以在一个表中存储超过单个磁盘或文件系统分区所能容纳的数据量。
-
失去价值的数据通常可以通过删除包含该数据的分区(或多个分区)来轻松移除。相反,添加新数据的过程在某些情况下可以通过为存储特定数据而创建一个或多个新分区来加速。此外,由于分区可以在创建分区表后进行更改,您可以重新组织数据以优化频繁查询,这些查询可能在最初设置分区方案时并不常用。由于分区可以自动排除不匹配的分区(以及它们包含的行),这通常被称为分区修剪。有关更多信息,请参阅第26.4节,“分区修剪”。
-
某些查询可以得到极大的优化,因为满足给定
WHERE
子句的数据可以只存储在一个或多个分区上,这会自动将任何剩余分区排除在搜索之外。由于分区可以在创建分区表后进行更改,因此您可以重新组织数据以增强在最初设置分区方案时可能不常使用的频繁查询。这种排除不匹配分区(以及它们包含的任何行)的能力通常称为分区修剪。有关更多信息,请参阅第 26.4 节“分区修剪”。此外,MySQL 支持对查询进行显式分区选择。例如,
SELECT * FROM t PARTITION (p0, p1) WHERE c < 5
只会从分区p0
和p1
中选择那些满足WHERE
条件的行。在这种情况下,MySQL 不会检查表t
的其他分区;这可以显著加快查询速度,当您已经知道要查看哪个分区或多个分区时。支持对DELETE
、INSERT
、REPLACE
、UPDATE
和LOAD DATA
、LOAD XML
的查询进行分区选择。有关这些语句的更多信息和示例,请查看它们的描述。