SQL按范围分区是关系型数据库中常用的表分区策略,核心逻辑是按照表中某个列的数值区间,将数据划分到不同的物理分区中,每个分区独立存储对应范围的数据,查询时数据库可以自动定位到目标分区,减少全表扫描的开销。

RANGE分区的基本概念
RANGE分区属于水平分区的一种,分区键通常是日期、数值这类具有连续特性的列。比如按照订单表的创建时间分区,2023年1月的数据放到分区p202301,2023年2月的数据放到分区p202302,以此类推。这种分区方式非常适合按照时间维度查询的场景,比如查询某个月份的订单数据,数据库只需要扫描对应月份的分区即可。
RANGE分区的创建语法
创建RANGE分区表的基本语法如下,需要指定分区键和每个分区的范围边界:
-- 创建RANGE分区表的基本语法
CREATE TABLE 表名 (
列1 数据类型,
列2 数据类型,
...
)
PARTITION BY RANGE (分区键列) (
PARTITION 分区名1 VALUES LESS THAN (边界值1),
PARTITION 分区名2 VALUES LESS THAN (边界值2),
...
PARTITION 分区名N VALUES LESS THAN (边界值N)
);
这里的VALUES LESS THAN表示分区的上限,分区会存储小于该边界值且大于等于前一个分区边界值的数据,第一个分区的下限是负无穷。
RANGE分区实际示例
示例1:按数值范围分区
我们创建一个用户积分表,按照用户积分范围分区,不同积分段的用户数据放到不同分区:
-- 创建用户积分表,按积分范围RANGE分区
CREATE TABLE user_score (
user_id INT,
score INT,
create_time DATE
)
PARTITION BY RANGE (score) (
-- 积分小于1000的用户
PARTITION p_low VALUES LESS THAN (1000),
-- 积分1000到2999的用户
PARTITION p_mid VALUES LESS THAN (3000),
-- 积分3000到5999的用户
PARTITION p_high VALUES LESS THAN (6000),
-- 积分大于等于6000的用户
PARTITION p_top VALUES LESS THAN (MAXVALUE)
);
插入测试数据后,可以通过查询分区信息确认数据分布:
-- 插入测试数据 INSERT INTO user_score VALUES (1, 500, '2024-01-01'); INSERT INTO user_score VALUES (2, 2000, '2024-01-02'); INSERT INTO user_score VALUES (3, 4000, '2024-01-03'); INSERT INTO user_score VALUES (4, 8000, '2024-01-04'); -- 查询每个分区的数据量(MySQL示例) SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'user_score';
示例2:按时间范围分区
时间范围是RANGE分区最常见的使用场景,以下是按订单创建时间按月分区的示例:
-- 创建订单表,按创建时间按月RANGE分区
CREATE TABLE order_info (
order_id INT,
user_id INT,
order_amount DECIMAL(10,2),
create_time DATE
)
PARTITION BY RANGE (TO_DAYS(create_time)) (
-- 2024年1月的数据
PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')),
-- 2024年2月的数据
PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')),
-- 2024年3月的数据
PARTITION p202403 VALUES LESS THAN (TO_DAYS('2024-04-01')),
-- 后续月份的数据统一放到这个分区
PARTITION p_future VALUES LESS THAN (MAXVALUE)
);
查询2024年2月的订单时,数据库会自动扫描p202402分区,不需要遍历全表:
-- 查询2024年2月的订单,只扫描p202402分区 SELECT * FROM order_info WHERE create_time >= '2024-02-01' AND create_time < '2024-03-01';
RANGE分区使用注意事项
- 分区键必须是主键或者唯一索引的一部分,否则创建分区表时会报错。
- 分区的边界值必须是递增的,不能出现后面的分区边界小于前面分区边界的情况。
- 如果插入的数据不在任何已有分区的范围内,且没有定义
VALUES LESS THAN (MAXVALUE)的分区,会插入失败。 - 分区并不是越多越好,过多的分区会增加数据库元数据管理的开销,建议根据业务查询频率合理划分分区数量。
- 不同数据库对RANGE分区的语法支持略有差异,实际使用时需要参考对应数据库的官方文档。
RANGE分区的适用场景
RANGE分区最适合以下场景:
- 数据有明显的时间维度,且查询经常按照时间范围过滤,比如日志表、订单表、统计表。
- 需要定期清理历史数据,比如删除3个月前的订单数据,直接删除对应分区即可,比DELETE语句效率高很多。
- 大表查询性能不足,且查询条件经常命中分区键的范围,通过分区裁剪可以大幅提升查询速度。