GBase 8a
其他
文章
GBase 8a LIST 分区表速览
发表于2026-06-30 17:02:1239次浏览0个评论
GBase 8a LIST 分区表速览
一、什么是 LIST 分区
LIST 分区按列的离散枚举值划分数据,每个分区对应一组明确的值列表。与 RANGE 分区(连续范围)不同,LIST 分区适合按状态码、业务类型、部门编号等整型枚举维度组织数据。
⚠️ GBase 8a 的 LIST 分区不支持
LIST COLUMNS语法,分区表达式必须返回整数值。字符串列需改用 KEY 分区或整型编码列(见下文)。
二、建表语法
CREATE TABLE 表名 (
列定义, ...
)
PARTITION BY LIST (expr) (
PARTITION 分区名 VALUES IN (值1, 值2, ...),
PARTITION 分区名 VALUES IN (值1, 值2, ...),
...
);
语法要点:
| 组成部分 | 说明 |
|---|---|
PARTITION BY LIST(expr) |
expr 是整型列名或返回整数的函数表达式(如 列名、QUARTER(date_col)) |
PARTITION 名称 |
自定义分区名,建议有业务含义 |
VALUES IN (...) |
该分区接收的离散值列表,值之间为"或"关系 |
三、使用示例
示例 1:按部门编号直接分区
CREATE TABLE emp_list (
id INT,
name VARCHAR(50),
dept_id INT
)
PARTITION BY LIST (dept_id) (
PARTITION p_odd VALUES IN (1, 3, 5, 7),
PARTITION p_even VALUES IN (2, 4, 6, 8)
);
INSERT INTO emp_list VALUES (1, 'ZhangSan', 3); -- 进入 p_odd
INSERT INTO emp_list VALUES (2, 'LiSi', 6); -- 进入 p_even
SELECT * FROM emp_list ORDER BY id;
-- +------+-----------+---------+
-- | id | name | dept_id |
-- +------+-----------+---------+
-- | 1 | ZhangSan | 3 |
-- | 2 | LiSi | 6 |
-- +------+-----------+---------+
示例 2:用 QUARTER() 函数按季度分区
GBase 8a 的 LIST 分区表达式支持内置函数,如按日期取季度:
CREATE TABLE orders (
order_id BIGINT,
amount DECIMAL(12,2),
deal_date DATE
)
PARTITION BY LIST (QUARTER(deal_date)) (
PARTITION p_q1 VALUES IN (1),
PARTITION p_q2 VALUES IN (2),
PARTITION p_q3 VALUES IN (3),
PARTITION p_q4 VALUES IN (4)
);
INSERT INTO orders VALUES (1, 100.50, '2025-02-15'); -- 进入 p_q1
INSERT INTO orders VALUES (2, 200.00, '2025-07-20'); -- 进入 p_q3
SELECT * FROM orders;
-- +-----------+---------+------------+
-- | order_id | amount | deal_date |
-- +-----------+---------+------------+
-- | 1 | 100.50 | 2025-02-15 |
-- | 2 | 200.00 | 2025-07-20 |
-- +-----------+---------+------------+
示例 3:字符串列怎么分区?——用 KEY 分区
GBase 8a 的 LIST 分区不支持 LIST COLUMNS 语法(试图使用会报 ERROR 1064),如果想按地区等字符串列分区,应使用 KEY 分区,它支持所有数据类型,查询同样触发分区裁剪:
CREATE TABLE sales_regional (
sale_id BIGINT,
region VARCHAR(20),
amount DECIMAL(12,2)
)
PARTITION BY KEY (region) (
PARTITION p_north,
PARTITION p_east,
PARTITION p_south,
PARTITION p_west
);
INSERT INTO sales_regional VALUES (1, 'Beijing', 500.00);
INSERT INTO sales_regional VALUES (2, 'Shanghai', 600.00);
INSERT INTO sales_regional VALUES (3, 'Guangzhou', 400.00);
-- 分区裁剪生效:EXPLAIN 中 TABLE 列为 sales_regional[DIS](分布式扫描)
EXPLAIN SELECT * FROM sales_regional WHERE region='Beijing';
-- | ID | MOTION | OPERATION | TABLE | CONDITION |
-- | 00 | [RESULT] | SCAN | sales_regional[DIS] | (region{S} = 'Beijing') |
如果业务上必须显式控制值→分区的映射关系,可以加一个整型编码列来驱动 LIST 分区:
CREATE TABLE sales_regional_code (
sale_id BIGINT,
region VARCHAR(20),
region_code TINYINT, -- 1=华北, 2=华东, 3=华南, 4=西部
amount DECIMAL(12,2)
)
PARTITION BY LIST (region_code) (
PARTITION p_north VALUES IN (1), -- 北京, 天津, 河北...
PARTITION p_east VALUES IN (2), -- 上海, 江苏, 浙江...
PARTITION p_south VALUES IN (3), -- 广东, 广西, 海南...
PARTITION p_west VALUES IN (4), -- 四川, 重庆, 云南...
PARTITION p_other VALUES IN (5)
);
INSERT INTO sales_regional_code VALUES (1, 'Beijing', 1, 500.00);
INSERT INTO sales_regional_code VALUES (2, 'Shanghai', 2, 600.00);
SELECT * FROM sales_regional_code WHERE region_code = 1;
-- | sale_id | region | region_code | amount |
-- | 1 | Beijing | 1 | 500.00 |
示例 4:LIST 分区 + HASH 子分区
LIST 分区支持子分区(子分区类型仅限 HASH 或 KEY):
CREATE TABLE orders_sub (
order_id BIGINT,
dept_id INT,
amount DECIMAL(12,2)
)
PARTITION BY LIST (dept_id)
SUBPARTITION BY HASH (order_id)
SUBPARTITIONS 2 (
PARTITION p_odd VALUES IN (1, 3, 5, 7),
PARTITION p_even VALUES IN (2, 4, 6, 8)
);
INSERT INTO orders_sub VALUES (1, 1, 100.00);
INSERT INTO orders_sub VALUES (2, 2, 200.00);
SELECT * FROM orders_sub;
-- | order_id | dept_id | amount |
-- | 1 | 1 | 100.00 |
-- | 2 | 2 | 200.00 |
每个 LIST 分区内部按 order_id 哈希再拆为 2 个子分区,共 4 个物理分区。
四、分区管理操作
-- 新增分区
ALTER TABLE emp_list ADD PARTITION (
PARTITION p_extra VALUES IN (9, 10, 11)
);
-- 向新分区插入数据
INSERT INTO emp_list VALUES (5, 'NewGuy', 9);
-- SELECT: id=5, name='NewGuy', dept_id=9
-- 删除分区(数据物理删除,不可恢复,操作前请确认)
ALTER TABLE emp_list DROP PARTITION p_extra;
-- 查看分区定义(推荐,包含完整 DDL)
SHOW CREATE TABLE emp_list;
-- 输出中可见 PARTITION BY LIST (dept_id) 及各分区定义
-- 查看分区元信息
SELECT PARTITION_NAME, PARTITION_METHOD, TABLE_ROWS
FROM information_schema.PARTITIONS
WHERE TABLE_NAME = 'emp_list' AND TABLE_SCHEMA = 'your_db';
-- | PARTITION_NAME | PARTITION_METHOD | TABLE_ROWS |
-- | p_odd | LIST | 0 | ← MPP 下表行数恒为 0
-- | p_even | LIST | 0 |
-- 查看表状态(create_options 含 "partitioned" 即为分区表)
SHOW TABLE STATUS WHERE Name = 'emp_list';
-- Create_options: avg_row_length=160 partitioned
-- 查看执行计划
EXPLAIN SELECT * FROM emp_list WHERE dept_id = 3;
-- TABLE 列显示 emp_list[DIS],表示分布式扫描
关于 ANALYZE TABLE:
ANALYZE TABLE在部分 GBase 8a 版本中通过 gcluster(协调节点)执行时会报ERROR 1235: The query includes syntax that is not supported by gcluster。分区裁剪依赖的是表元数据而非统计信息,不执行 ANALYZE 不影响分区裁剪功能。
五、使用限制
| 限制项 | 说明 |
|---|---|
| 版本要求 | V9 及以上,V8 不支持分区 |
| 分区键类型 | LIST(expr) 要求 expr 返回整数;不支持 LIST COLUMNS(实测报 ERROR 1064) |
| 字符串列 | 不能用 LIST 分区,改用 KEY 分区或加整型编码列 |
| 主键约束 | 若表有主键/唯一键,分区键列必须包含在其中 |
| 值不可重叠 | 同一个值不能出现在多个分区的 VALUES IN 中 |
| 无 DEFAULT 分区 | 插入不在任何分区中的值直接报错 ERROR 1527: Table has no partition for value,务必预留兜底分区 |
| 子分区限制 | 仅限于 HASH / KEY 子分区,不支持 LIST-LIST、RANGE-LIST |
| 子分区个数 | 每个分区的子分区个数必须相同 |
| 分区总数 | 含子分区在内不超过 8192,建议控制在 50~200 |
| 分区列 | 不支持 UPDATE 操作 |
| NULL 值 | 需在某个分区中显式包含 VALUES IN (NULL),否则 NULL 写入报错 |
六、常见报错速查
| 报错 | 原因 | 解决 |
|---|---|---|
ERROR 1064 ... near 'COLUMNS' |
误用 MySQL 的 LIST COLUMNS 语法 |
改用 LIST(整型列) 或 KEY(列) |
ERROR 1527: Table has no partition for value |
插入的值不在任何分区的 VALUES IN 中 | 新增分区、预留兜底分区、或用 KEY 分区 |
ERROR 1235: ...not supported by gcluster |
通过协调节点执行了 ANALYZE TABLE | 分区裁剪不依赖 ANALYZE,可跳过 |
ERROR 1702: The PARTITION function returns the wrong type |
LIST 表达式返回了非整型 | 确认列/函数返回值为整型 |
七、小结
| 场景 | 推荐分区方式 | 实测 |
|---|---|---|
| 整型枚举列(状态码、类型码) | PARTITION BY LIST |
✅ |
| 日期提取季度/月份 | PARTITION BY LIST(QUARTER(col)) |
✅ |
| 字符串枚举列(地区、名称) | PARTITION BY KEY |
✅ |
| 需要二级分片 | LIST + HASH/KEY 子分区 | ✅ |
| 显示值→分区映射 | 整型编码列 + LIST | ✅ |
评论
登录后才可以发表评论
热门帖子
- 12025-12-01浏览数:183247
- 22023-05-09浏览数:26017
- 42023-09-25浏览数:19674
- 52020-05-11浏览数:18304