导读:本期聚焦于阳光创作的《MySQL子分区怎么用?使用子分区时需要注意哪些问题?》,敬请观看详情。分区表数据量大了之后,单个分区仍然可能变得臃肿,这时候子分区就派上用场了。子分区是在一级分区的基础上对每个分区再做一次细分,比如先按范围分区,再按哈希子分区,让数据分布更均匀、查询裁剪更精准。但子分区并不是随便加就能生效的,它有严格的语法限制:只有Range和List分区支持子分区,子分区类型只能是Hash或Key,而且每个一级分区下的子分区数量必须相同。此外,子分区键必须包含在主键或唯一键中,建表和后续维护也都有不少坑。本文将从子分区的基本语法讲起,结合实际建表示例,详细说明使用限制、查询优化效果以及常见的踩坑点,帮助你正确地用好MySQL子分区。

当单表数据量达到千万级甚至亿级时,很多DBA会想到用分区表来拆分数据。但有时候光是分区还不够,比如按照时间做了Range分区之后,每个分区内部的数据量依然巨大,单分区的索引体积和查询压力仍然居高不下。这时可以考虑在分区的基础上再做一层细分,也就是子分区(Subpartitioning)。子分区能够让数据分布更加均匀,也让分区裁剪在更细的粒度上生效。不过子分区的使用限制相当多,稍不注意就会建表失败或者达不到预期的优化效果。

MySQL子分区怎么用?使用子分区时需要注意哪些问题?

一、什么是子分区以及基本语法

子分区顾名思义,就是在分区的基础上再分区,也被称为复合分区(composite partitioning)。MySQL中子分区只能搭配两种一级分区类型使用:Range分区和List分区,而子分区本身只能采用Hash分区或Key分区。也就是说,你能遇到的组合只有四种:Range-Hash、Range-Key、List-Hash、List-Key。

下面是一个典型的Range-Hash复合分区建表语句,按照订单创建月份做范围分区,每个范围分区内再按用户ID做哈希子分区:

CREATE TABLE orders (
    order_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    amount DECIMAL(10,2),
    created_at DATETIME NOT NULL,
    PRIMARY KEY (order_id, created_at, user_id)
)
PARTITION BY RANGE (TO_DAYS(created_at)) (
    PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01'))
        (
            SUBPARTITION s0 COMMENT = '一号子分区',
            SUBPARTITION s1 COMMENT = '二号子分区'
        ),
    PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01'))
        (
            SUBPARTITION s2,
            SUBPARTITION s3
        )
);

写法上有两种风格:一种是用SUBPARTITION关键字逐个定义子分区,如上例所示;另一种是通过SUBPARTITION BY HASH(user_id) SUBPARTITIONS 4的方式让每个一级分区自动裂解成固定数量的子分区,这种写法更简洁,推荐在子分区不需要单独命名或指定存储位置时使用:

CREATE TABLE orders2 (
    order_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    created_at DATETIME NOT NULL,
    PRIMARY KEY (order_id, created_at, user_id)
)
PARTITION BY RANGE (TO_DAYS(created_at))
SUBPARTITION BY HASH(user_id)
SUBPARTITIONS 4 (
    PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')),
    PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')),
    PARTITION pmax VALUES LESS THAN MAXVALUE
);

二、子分区的使用限制与常见错误

子分区的限制比普通分区更严格,实际使用中最常见的报错基本都集中在以下几点。

第一,一级分区类型受限。如果你试图在Hash分区或者Key分区下面再建子分区,MySQL会直接报错。因为Hash和Key分区本身就是把数据均匀打散的,再套一层Hash没有意义。只有Range和List分区支持子分区,这是硬性规定,没有变通的办法。

第二,子分区数量必须一致。每个一级分区下的子分区个数必须相同,而且只能在建表时定义,建表之后无法通过ALTER TABLE增加或减少子分区的数量。如果p202401下面有两个子分区,p202402下面却定义了三个,建表就会失败。这一点和一级分区不同,一级分区是可以后续通过ADD PARTITION灵活扩展的。

第三,分区键必须纳入主键。如果表有主键或者唯一键,那么分区列和子分区列必须全部包含在这些键中。比如上面例子中,user_id和created_at都要出现在PRIMARY KEY里,否则会报每个分区键必须包含在表的每个唯一键中的错误。这个限制经常让业务上的主键设计被迫调整,需要在建表前规划清楚。

第四,子分区总数有上限。MySQL中一个表最多只能有8192个分区(含子分区),如果一级分区是36个月,每个分区下再切32个子分区,总数就是1152个,还算安全;但如果是按天分区再叠加子分区,很容易撞到上限,并且分区数量过多会显著拖慢打开表、执行计划生成等操作,反而得不偿失。

三、子分区对查询性能的影响与使用建议

子分区最大的价值在于分区裁剪(partition pruning)可以在两个维度上生效。当查询条件同时包含一级分区列和子分区列时,MySQL能够精确定位到具体的子分区,扫描的数据量会大幅减少。比如下面的查询,created_at用于裁剪Range分区,user_id用于裁剪Hash子分区:

EXPLAIN SELECT * FROM orders2
WHERE created_at >= '2024-01-01'
  AND created_at < '2024-02-01'
  AND user_id = 10086;

通过EXPLAIN观察partitions列,如果显示的是单个子分区名(如p202401_sp2这样的形式),说明两层裁剪都生效了;如果显示整个一级分区下的所有子分区,说明子分区裁剪没有命中,通常是因为查询条件中缺少子分区列,或者对子分区列做了函数包装导致裁剪失效。

在使用建议上,有几点经验值得参考。首先,子分区的粒度要结合查询模式来定,如果绝大多数查询都只按时间过滤,那么加子分区带来的收益有限,反而增加了维护复杂度;只有当高频查询经常同时携带另一个维度条件(如用户ID、地区ID)时,子分区才真正有价值。其次,子分区的数量建议保持在2到8个之间,过多没有意义,Hash子分区本身就是为了打散,几个足以让单分区数据量降下来。最后,要注意子分区的维护操作,虽然不能增减子分区数量,但可以对单个子分区执行TRUNCATE、REPAIR等操作,排查问题时可以按子分区粒度定位,信息系统的information_schema.PARTITIONS表中记录了每个子分区的行数,是监控数据分布是否均匀的重要依据。

总的来说,子分区是个好用但约束很多的特性。建表前先把一级分区列、子分区列和主键的关系理清楚,确认查询模式确实需要两个维度的裁剪,再动手设计,才能避免返工并真正发挥它的性能价值。

MySQL子分区子分区分区表修改时间:2026-09-07 01:12:31

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260907/51880.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。