RANGE分区是按列值连续范围将表划分为多个分区,适用于时间或数字字段;要求分区列类型为数值或日期、范围不重叠且连续覆盖,插入时自动路由至匹配分区。

SQL的RANGE分区是按列值的连续范围将表数据划分为多个分区,每个分区对应一个值区间,常用于时间字段(如日期)或数字主键的归档与查询优化。
什么是RANGE分区
RANGE分区要求分区列必须是数值型或日期型,且各分区范围不能重叠、必须连续覆盖(或明确指定MAXVALUE作为兜底)。MySQL、PostgreSQL(通过表继承模拟)、Oracle等主流数据库均支持,但语法细节略有差异。核心逻辑是:当插入一条记录时,数据库根据分区列的值自动将其路由到匹配的分区中。
RANGE分区的关键规则
必须满足以下条件:
- 分区列不能为NULL(除非显式允许并单独定义NULL分区)
- 每个分区需用VALUES LESS THAN定义上界,例如VALUES LESS THAN (20230101)
- 分区边界必须严格递增,不可跳过或倒序
- 最后一个分区建议用VALUES LESS THAN MAXVALUE,避免插入越界报错
- 不支持对已有非分区表直接添加RANGE分区,需重建表或使用ALTER TABLE ... PARTITION BY
MySQL RANGE分区完整示例
以订单表orders为例,按订单创建时间(order_date)做月度分区:
CREATE TABLE orders ( id BIGINT PRIMARY KEY, order_no VARCHAR(32), amount DECIMAL(10,2), order_date DATE ) PARTITION BY RANGE (YEAR(order_date) * 100 + MONTH(order_date)) ( PARTITION p_202301 VALUES LESS THAN (202302), PARTITION p_202302 VALUES LESS THAN (202303), PARTITION p_202303 VALUES LESS THAN (202304), PARTITION p_202304 VALUES LESS THAN (202305), PARTITION p_future VALUES LESS THAN MAXVALUE );
说明:这里用YEAR(date)*100+MONTH(date)生成形如202301的整数,便于RANGE分区;查询WHERE order_date BETWEEN '2023-02-01' AND '2023-02-28'时,优化器可自动裁剪到p_202302分区,大幅减少扫描量。
常见问题与注意事项
容易踩的坑:
- 误用字符串函数(如DATE_FORMAT)导致无法分区——RANGE只接受确定性表达式,且必须返回数值或日期
- 忘记建索引:分区本身不替代索引,
order_date仍建议加普通索引或前缀索引 - 分区过多(如每天一分区)会增加元数据开销,一般按月或季度更合理
- 删除历史分区可用
ALTER TABLE orders DROP PARTITION p_202301,比DELETE更快且不锁全表
基本上就这些。RANGE分区不是万能的,但对时间序列类大表的冷热分离和快速归档非常实用。










