使用DWS行列共存表
场景介绍
在实际业务场景中,一张表往往既需要支持高并发的点查与更新(如订单、账单、日志等),也需要支持高效的批量查询与聚合分析(如统计报表、趋势分析)。传统的行存与列存各有所长:
- 行存(Row Store):适合点查、写入频繁的实时场景,如根据订单号查询订单详情。
- 列存(Column Store):适合大批量分析型查询,如统计一段时间内的总交易额。
DWS提供的行列共存表(也称行列混存表),是一种创新的混合存储模式:在一张表中同时存储行格式数据和列格式数据,两种格式各自独立维护、同步更新,由查询优化器根据实际查询路径选择最优访问方式。
其核心优势在于:
- 无需拆表或复制数据:一张表即同时支持明细查询与批量分析。
- 由系统自动选择最优路径:查询点查字段时走行存,查询聚合字段时走列存,无需额外开发处理。
- 性能最优兼顾:在不牺牲OLTP性能的同时,兼具OLAP查询效率。
- 兼容原有行表设计:无需调整应用结构,快速享受列存优化/行存优化带来的性能收益。
- 统一管理、降低运维成本:一张物理表即覆盖两种场景,简化数据同步、备份与权限控制。
本最佳实践文档将介绍如何设计使用行列共存表结构,结合典型场景和性能对比,帮助您在业务系统中实现更高效的数据处理能力。
实时场景下表类型对比(行存表 / 列存表 / 行列共存表)
对比维度 |
行存表(orientation='row') |
HStore表(hstore_opt表) |
行列共存表(storage_mode='mix') |
---|---|---|---|
存储架构 |
原生行存引擎(不基于列存) |
HStore_opt列存 |
自研行模式和列存HStore_opt表共存 |
点查性能(主键) |
极优(5) |
较差(2) |
优(4) |
批量入库性能 |
较差(2) |
极优(5) |
优(4) |
实时入库性能 |
极优(5) |
极优(5) |
极优(5) |
聚合/分析性能 |
⬛ 差(1) |
极优(5) |
极优(5) |
空间占用 |
⬛ 高(1) |
极低(5) |
一般(3) |
空间膨胀 |
极优(5) |
极优(5) |
优(4) |
DWS列存特殊优化 |
❌ 不支持 |
✅ 支持 |
✅ 支持 |
约束限制
- 仅9.1.1.100及以上版本支持。
- 需使用HStore表,即enable_hstore_opt参数设置为开。
- 不支持存算分离V3表。
- 不支持开启HStore表的enable_light_update选项。
- 不支持binlog表,物化视图。
- 小批量的实时copy入库,相比HStore表,存在10%的性能劣化。
- 行列混存表只能和行列混存表进行exchange,扩容重分布后,禁止使用exchange。
使用建议
- 仅OLTP场景(例如高频点查、写入):若对空间使用敏感,推荐使用行列共存表,兼顾空间与点查性能的折中方案,若空间不敏感,追求极致效果的场景推荐行存表。
- 仅OLAP场景(例如统计分析、报表):推荐使用HStore的列存表。
- 明细与统计查询并存,且字段冷热难以区分:推荐使用行列共存表模式,各个场景性能最优;
- 实时入库上,推荐使用PBE AddBatch方式入库。
- 建议不要轻易修改列定义,若触发数据重写,行列共存表会重写行存部分整个数据,性能开销较大。
语法参考
以下是创建行列共存表语法,更多请参见CREATE TABLE语法章节(仅9.1.1.100及以上版本支持)。
1 2 3 4 5 6 7 8 |
CREATE TABLE <表名> ( <列定义> ) WITH ( orientation = column, -- 基于列式的存储架构 enable_hstore_opt = on, -- 开启 hstore_opt 能力 storage_mode = 'mix' -- 指定建立行列共存表 ); |
示例:
-- 行列共存模式:同时存储行格式与列格式数据,适用于明细+分析混合业务 CREATE TABLE tbl_mix ( a INT, b TEXT ) WITH ( orientation = column, enable_hstore_opt = on, storage_mode = 'mix' );
使用行列混存表示例
- 建立一个简单的数据表。
1 2 3
DROP TABLE IF EXISTS data; CREATE TABLE data(a INT, b BIGINT, c VARCHAR(10), d VARCHAR(10)); INSERT INTO data values(generate_series(1,100),1,'asdfasdf','gergqer');
- 扩充表数据至20W。
1 2 3 4 5 6 7 8 9 10 11 12
INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; INSERT INTO data SELECT * FROM data; SELECT COUNT(*) FROM data;
- 构造一个简单的行列共存表。
1 2 3 4 5 6 7 8 9 10 11 12
DROP TABLE IF EXISTS rowmode_test1; CREATE TABLE rowmode_test1 ( a INT, b BIGINT, c VARCHAR(10), d VARCHAR(10) ) WITH ( orientation = column, enable_hstore_opt = on, storage_mode = 'mix' );
- 将数据导入行列共存表。
1
INSERT INTO rowmode_test1 SELECT * FROM data;