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 TABLEANALYZE 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

评论

登录后才可以发表评论