Mysql分区

一、分区的优点

  • 提高查询性能:当查询条件涉及分区键时,数据库可以只扫描相关分区,而不是整个表。
  • 管理方便:可以单独对某个分区进行维护,比如删除旧数据时可以直接删除整个分区,效率更高。

二、基本分区类型

2.1 RANGE 分区(最常用)

根据一个给定连续区间的列值,将数据分配到不同的分区。通常用于日期或时间相关的列。

  • 原理:为每个分区定义一個范围,当插入的数据的分区列值落入某个范围时,就被存储到对应的分区。
  • 常见场景 :按年、按月分区日志表或交易记录表。可以很方便地删除旧数据(直接 DROP PARTITION)。
  • 示例:
sql 复制代码
CREATE TABLE sales (
    order_date DATE,
    amount DECIMAL(10, 2)
)
PARTITION BY RANGE (YEAR(order_date)) (
    PARTITION p_2020 VALUES LESS THAN (2021),
    PARTITION p_2021 VALUES LESS THAN (2022),
    PARTITION p_2022 VALUES LESS THAN (2023),
    PARTITION p_max VALUES LESS THAN MAXVALUE -- 用于存储未来所有超出定义范围的数据
);
  • 表结构定义: order_date DATE:定义一个名为order_date的日期类型的列。 amount DECIMAL(10, 2):定义一个名为amount的十进制数字列,总位数为10,小数点后保留2位。

  • 分区方式: PARTITION BY RANGE (YEAR(order_date)):表示按照order_date列的年份范围进行分区。YEAR(order_date)会提取日期中的年份,然后根据年份的范围来划分数据存储的不同区域。 分区语句是使用RANGE分区,并且分区表达式是YEAR(order_date)。这里的分区条件是用LESS THAN来定义的。对于RANGE分区,每个分区的定义是使用VALUES LESS THAN (value)来指定一个上限。分区的范围是从最低值开始,到指定的value为止,但不包括value。注意:value必须是一个常量表达式,且通常为整数或日期类型(取决于分区键的数据类型)。最后一个分区使用了MAXVALUE,这是一个特殊的值,表示所有大于之前分区上限的值都会存储在这个分区中。 分区键可以是表达式,也可以是单个列。但是,在分区表达式中使用的列必须是表的主键的一部分,或者唯一索引(如果表有唯一索引)必须包含分区表达式中所有的列。具体规则如下: 如果表有主键,则分区键必须是主键的一部分。 如果表有唯一索引,则分区键必须是唯一索引的一部分。

2.2 List 分区

类似于 RANGE 分区,但分区是基于一个离散的、不连续的值的列表。

  • 原理:为每个分区定义一個值列表,当插入的数据的分区列值等于列表中的任何一个值时,就被存储到对应的分区。
  • 常见场景:按地区、按类别等离散值分区。例如,根据国家或状态代码分区。
  • 示例:
sql 复制代码
CREATE TABLE employees (
    id INT,
    name VARCHAR(100),
    region_code INT
)
PARTITION BY LIST (region_code) (
    PARTITION p_north VALUES IN (1, 2, 3),   -- 区域代码为 1,2,3 的放在北部分区
    PARTITION p_south VALUES IN (4, 5, 6),
    PARTITION p_west VALUES IN (7, 8, 9),
    PARTITION p_other VALUES IN (DEFAULT)     -- 存储不在上述列表中的值
);
  • 表结构定义:
  1. CREATE TABLE employees (: 创建一个名为employees的表。
  2. id INT,: 定义了一个整数类型的列id,用于存储员工的ID。
  3. name VARCHAR(100),: 定义了一个可变字符串类型的列name,最大长度为100个字符,用于存储员工的姓名。
  4. region_code INT: 定义了一个整数类型的列region_code,用于存储区域代码。
  5. ) PARTITION BY LIST (region_code) (: 指定按照region_code列进行列表分区。列表分区是根据某个列的离散值来划分分区,每个分区包含一组指定的值。
  6. PARTITION p_north VALUES IN (1, 2, 3),: 创建一个名为p_north的分区,用于存储region_code值为1、2、3的数据。这些数据代表北部分区。
  7. PARTITION p_south VALUES IN (4, 5, 6),: 创建一个名为p_south的分区,用于存储region_code值为4、5、6的数据。这些数据代表南部分区。
  8. PARTITION p_west VALUES IN (7, 8, 9),: 创建一个名为p_west的分区,用于存储region_code值为7、8、9的数据。这些数据代表西部分区。
  9. PARTITION p_other VALUES IN (DEFAULT): 创建一个名为p_other的分区,用于存储region_code不在上述列表中的任何值。DEFAULT关键字表示所有未在前面分区中指定的值都会存储在这个分区中。
  • 总结: 该表根据region_code列的值将数据分布到四个不同的分区中。每个分区对应一个区域(北、南、西和其他)。这种分区方式可以优化查询性能,特别是当查询条件涉及region_code时,数据库可以只扫描相关的分区,提高查询效率。同时,分区也有助于数据的管理和维护,比如可以独立备份或维护某个分区
  • 列表分区的特点: 列表分区(LIST Partitioning)是一种数据库分区策略,它根据某个列的离散值(即不连续的值,如类别、状态码、地区代码等)来划分数据。每个分区会包含一组指定的值,当插入数据时,数据库会根据这个列的值决定将数据放入哪个分区。

2.3 KEY 分区

类似于 HASH 分区,但 MySQL 使用服务器自身的哈希函数(基于 PASSWORD() 函数相同的算法)。KEY 分区只支持一列或多列(而 HASH 分区支持表达式)

  • 原理:如果表有主键,但主键不适用于 RANGE 或 LIST 分区,KEY 分区是一个很好的选择,因为它通常使用主键作为分区键。
  • 与 HASH 的区别:KEY 分区使用 MySQL 内置的哈希算法,而 HASH 分区使用用户指定的表达式。
  • 如何选择KEY分区的分区键?如果表有主键 :通常可以选择主键的一部分或全部作为分区键。注意,如果表有主键,则分区键必须是主键的一部分或全部。也就是说,分区键必须是主键或唯一索引的一部分(除非没有主键或唯一索引)。 如果表没有主键:可以选择任何列作为分区键,但最好选择那些在查询中经常使用的列,且该列的值分布均匀。
  • 示例:
sql 复制代码
CREATE TABLE log_messages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message TEXT
)
PARTITION BY KEY (id) -- 使用主键 id 作为分区键
PARTITIONS 2;
  • 分区部分:
  1. PARTITION BY KEY (id):表示按照键进行分区。KEY分区是MySQL中一种分区类型,它使用哈希函数对分区键进行计算,从而确定数据行应该放在哪个分区。这里的分区键是主键id
  2. PARTITIONS 2:表示创建2个分区。分区数可以自己指定。在创建表时,你可以通过PARTITIONS n来指定分区的数量,其中n是一个正整数。这个n值可以根据你的需求来设定,但是通常需要考虑数据的分布、查询性能以及管理便利性等因素。 在KEY分区和HASH分区中,分区的数量是由用户指定的。而在RANGE分区和LIST分区中,分区的数量是由你定义的分区范围或列表值决定的,不需要指定分区数量,而是直接列出每个分区。例如,在KEY分区中,你可以指定任意数量的分区(只要在MySQL限制范围内,通常最大为1024个分区,但实际可能受操作系统和存储引擎的限制)
  • 实际效果:
  1. 表在物理上会被分成两个独立的文件(每个分区对应一个文件),但逻辑上仍然是一个表。
  2. 查询时,如果条件中包含分区键(id),MySQL可以只扫描一个分区(分区修剪),从而提高查询效率。
  • 示例:
  1. 表在物理上会被分成两个独立的文件(每个分区对应一个文件),但逻辑上仍然是一个表。
  2. 查询时,如果条件中包含分区键(id),MySQL可以只扫描一个分区(分区修剪),从而提高查询效率。
  • 总结: 该表根据region_code列的值将数据分布到四个不同的分区中。每个分区对应一个区域(北、南、西和其他)。这种分区方式可以优化查询性能,特别是当查询条件涉及region_code时,数据库可以只扫描相关的分区,提高查询效率。同时,分区也有助于数据的管理和维护,比如可以独立备份或维护某个分区
  • 列表分区的特点: 列表分区(LIST Partitioning)是一种数据库分区策略,它根据某个列的离散值(即不连续的值,如类别、状态码、地区代码等)来划分数据。每个分区会包含一组指定的值,当插入数据时,数据库会根据这个列的值决定将数据放入哪个分区。

2.4 COLUMNS 分区(RANGE COLUMNS 和 LIST COLUMNS)

这是对标准 RANGE 和 LIST 分区的扩展,提供了更强大的功能。

  • 原理RANGE COLUMNS允许使用多个列来定义范围。范围是基于元组(多个列值的组合)的比较,而不是单个标量值。LIST COLUMNS允许使用多个列来定义值列表。
  • 优势 :支持非整数类型的列(如 DATE, DATETIME, CHAR, VARCHAR)作为分区键,而无需使用函数(如 YEAR())。支持多列分区键。
  • 示例(RANGE COLUMNS):
sql 复制代码
CREATE TABLE rcx (
    a INT,
    b INT,
    c CHAR(3),
    d INT
)
PARTITION BY RANGE COLUMNS(a, b, c) (
    PARTITION p0 VALUES LESS THAN (5, 10, 'mmm'), -- 比较的是 (a, b, c) 这个元组
    PARTITION p1 VALUES LESS THAN (10, 20, 'zzz'),
    PARTITION p2 VALUES LESS THAN (MAXVALUE, MAXVALUE, MAXVALUE)
);
  • 复合分区(子分区):
  1. 原理:先使用一种分区方式(如 RANGE),然后在每个分区内再使用另一种分区方式(如 HASH)。

  2. 常见场景:希望对数据先进行粗粒度划分(如按年),再在每个年份内进行细粒度的均匀分布。

  3. 示例

sql 复制代码
    CREATE TABLE ts (
    id INT,
    purchased DATE
)
PARTITION BY RANGE (YEAR(purchased)) -- 第一级分区:按年
SUBPARTITION BY HASH (TO_DAYS(purchased)) -- 第二级分区:按天哈希
SUBPARTITIONS 2 ( -- 每个一级分区下面再分成 2 个子分区
    PARTITION p0 VALUES LESS THAN (2021),
    PARTITION p1 VALUES LESS THAN (2022),
    PARTITION p2 VALUES LESS THAN MAXVALUE
);

三、 总结与选择建议

分区类型 关键字 适用场景
RANGE PARTITION BY RANGE 按时间顺序的范围数据,易于归档和删除旧数据。
LIST PARTITION BY LIST 按离散的、分类的值进行分区,如地区、状态。
HASH PARTITION BY HASH 主要目的是将数据均匀分布,提高并发性能。
KEY PARTITION BY KEY 与 HASH 类似,但使用内置算法,常用于主键。
COLUMNS PARTITION BY RANGE/LIST COLUMNS 支持多列和非整数类型作为分区键,更灵活。
  • 重要注意事项:
  1. 分区键必须是表主键或唯一索引的一部分。
  2. 分区并不是性能优化的"银弹",使用不当反而会降低性能。
  3. 在 MySQL 8.0 中,InnoDB 是唯一支持原生分区的存储引擎。
相关推荐
檀越剑指大厂3 小时前
让数据触手可及采用Chat2DB+cpolar重构数据库操作体验
数据库·重构
朝九晚五ฺ3 小时前
【Redis学习】Redis中常见的全局命令、数据结构和内部编码
数据库·redis·学习
qq_508823403 小时前
金融数据库--下载全市场股票日线行情数据
数据库·金融
DemonAvenger3 小时前
MySQL性能优化案例分析:从问题到解决方案
数据库·mysql·性能优化
老华带你飞4 小时前
寝室快修|基于SprinBoot+vue的贵工程寝室快修小程序(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序·毕设·贵工程寝室快修
fendouweiqian4 小时前
idea中使用database TLS异常处理
数据库·https·intellij-idea
小志开发9 小时前
SQL从入门到起飞:完整学习数据库与100+练习题
数据库·sql·学习·mysql·oracle·sqlserver·navcat