GaussDB(DWS)表类型选型的最佳实践

举报
QWERT886 发表于 2025/12/01 16:14:00 2025/12/01
【摘要】 数据库的存储模型直接影响数据处理的性能与效率,本文对当前dws支持的表类型进行介绍,从存储格式进行分类,对各种类型的表的适用场景进行介绍,并提供了一些简单的使用实例,方便业务进行表选型和开发。

GaussDB(DWS)表类型选型的最佳时间

1. 前言

  • 适用版本:【9.1.1(及以上)】

数据库的存储模型直接影响数据处理的性能与效率,本文对当前dws支持的表类型进行介绍,从存储格式进行分类,对各种类型的表的适用场景进行介绍,并提供了一些简单的使用实例,方便业务进行表选型和开发。

2. 表的存储格式

从数据的存储结构上看,DWS支持两种存储格式:行存,列存。

  • 行存表:以数据行(Row)为最小物理存储单元,同一行的所有字段在物理上相邻连续存储(包括空值占位)。可以通过tid定位到一整行的数据。

行存表的数据物理存储示例:

| ID  | Name  | Age | Salary | Department | 
|-----|-------|-----|--------|------------|
| 001 | 张三  | 30  | 15000  | 技术部     | ← 完整行数据连续存储
| 002 | 李四  | 28  | 12000  | 市场部     |
  • 列存表:以数据列(Column)为最小物理存储单元,每列的数据连续存储,同列数据连续排列,不同列独立存储为不同的存储单元。

列存表的数据物理存储示例:

Column: ID| 001 | 002 | 003 |...
Column: Name    → | 张三 | 李四 | 王五 |...
Column: Age     → | 30 | 28 | 35 |...

3. DWS支持的表类型

目前DWS支持的表类型有:行存表,列存表2.0,hstore表,存算分离表,行列混存表。

  • DWS的系统表以及业务默认创建的表都是行存表。
  • 列存2.0,hstore表,存算分离表和行列混存表都属于列存表,这几种列存表都是以数据列存储为基础演化出来的,分别适用于不同的业务场景。

4. 表类型的介绍

4.1 行存表

行存表的一行数据可以通过一个位置指针(索引)一次找到,并且在读取时一次读取至少一整行数据。

基于以上特点,行存储的优势主要有两个方面:

  • 点查性能好:在点查场景下可以直接索引到某行数据的元组位置;
  • 更新效率高:行存储在实时并发入库,并发更新方面都比较有优势。

但是也有一些缺点:

  • 存储时空间占用大:当前DWS采用多版本保存更新前后的数据,造成脏数据也占用存储空间;
  • 读放大:读取时需要读取一整个页面和元组,如果是大宽表,但是又只读取一两列数据的情况下,读放大的问题比较严重。

对于传统的OLTP业务,数据需要进行频繁的增删改查的场景,比较适合使用行存表。

举例:

-- 默认类型,指定 ORIENTATION = ROW 或者默认即可。
CREATE TABLE table_row
(
    c1 INT,
    c2 TEXT
) WITH (ORIENTATION = ROW);

4.2 列存表

行形式存储的表如果涉及到分析查询场景,特别是在数据量大且复杂的查询时,就会遇到性能瓶颈,这时可以选择列存储。

列存储的优势主要有两方面:

  • 批量查询性能好:当分析查询只涉及某列或者某几列,不需要访问无关列,特别是在表的宽度比较大时(如一千列),优势更加明显;
  • 空间占用小:列存储支持压缩,而且由于单列数据类型相同,压缩性能更高。

在OLAP场景下,优选列存表。

4.2.1 列存2.0

列存2.0表是最初的列存表,各列数据按一定数量组成一个存取单元(CU),压缩后写入一个物理文件中,通过辅助表控制以CU为单位的事务可见性。

列存2.0表目前在已上线的各种业务中广泛使用。

举例:

-- 指定 ORIENTATION = COLUMN 选项
CREATE TABLE table_col
(
    c1 INT,
    c2 TEXT                                     
) WITH (ORIENTATION = COLUMN);

4.2.2 hstore表(hstore-opt表)

列存2.0虽然在海量复杂查询方面相比行存表有优势,但是也存在比较明显的短板:由于可见性基于CU,所以基本无法支持并发更新入库。

随着业务复杂程度的提升和实时入库+查询诉求越来越多,hstore表应运而生。hstore表融合行存和列存的优势,在列存2.0的基础上业务入库并发进行了优化:使用一个行存表存储实时的增删改操作信息,然后通过后台线程将行存表数据merge到CU中。

hstore表解决了列存2.0表的以CU为单位进行并发的问题,支持上游增删改操作实时并发入库,数据merge到CU后又保证了数据的压缩能力和分析能力。

由于近些年实时业务的需求越来越多,hstore表已逐步取代列存2.0表,成为首选的列存表类型。

举例:

-- 在列存的基础上指定 ENABLE_HSTORE_OPT = TRUE 选项
CREATE TABLE table_hstore
(
    c1 INT,
    c2 TEXT                                     
) WITH (ORIENTATION = COLUMN, ENABLE_HSTORE_OPT = TRUE);

4.2.3 存算分离表

hstore表解决了实时业务的问题,但是由于列存表的AppendOnly属性,实时业务中大量的并发插入或更新会导致CU文件快速膨胀,而EVS存储价格不低,所以用户成本很高。

存算分离表在hstore表的基础上将CU文件存储到OBS(华为分布式对象存储,一种高可靠、低成本的海量持久化存储产品)中,搭配本地EVS盘的diskcache缓存能力,既可以尽可能的保证读取和写入的性能,又能有效降低用户成本。同时依托OBS的分布式存储能力,可以做到存储无线扩展,计算能力快速扩缩。

对于比较重视存储成本以及弹性能力的业务,可以选择存算分离表。

举例:

-- 需要选择存算分离集群
-- 在hstore表的基础上增加 COLVERSION = 3.0 选项
CREATE TABLE table_v3
(
    c1 INT,
    c2 TEXT                                     
) WITH (ORIENTATION = COLUMN, ENABLE_HSTORE_OPT = TRUE, COLVERSION = 3.0);

4.2.4 行列混存表

列存2.0、hstore表、存算分离表虽然在批量查询、实时入库、空间管理方面都做了各种优化,但是还还是无法做到行存表的点查性能。行列混存表则用空间换时间,将行列格式混合存储,通过占用更多的空间来换取点查性能的提升。

行列混存表在一张表中同时存储行格式数据和列格式数据,两种格式各自独立维护、同步更新,由查询优化器根据实际查询路径选择最优访问方式,通过列存固有的过滤优化能力实现更智能的I/O路径控制,自动选择访问行/列格式数据。确保提供列存储高压缩、高吞吐优势的同时,保留行存储对局部数据的灵活访问能力。

行列混存表适用于混合查询场景下的高效数据调度。行列混存表可以显著降低整体I/O开销,同时提升数据命中率与查询性能。

目前行列混存表还处于POC阶段。

举例:

-- 在hstore表的基础上增加 STORAGE_MODE = MIX 选项
CREATE TABLE table_mix
(
    c1 INT,
    c2 TEXT                                     
) WITH (ORIENTATION = COLUMN, ENABLE_HSTORE_OPT = TRUE, STORAGE_MODE = MIX);

4. 选型建议

行存储和列存储各有优势,没有绝对的优劣之分。行存储在事务处理方面表现出色,而列存储在大数据分析领域优势明显。随着技术的发展,二者的界限正逐渐模糊,现代数据库系统越来越多地采用混合策略来兼顾不同场景的需求。数据库选型时,应根据具体的应用场景、查询模式和性能要求来选择合适的存储模型。

表类型 行存表 列存2.0 Hhstore表 存算分离表 行列混存表
数据存储方式 以元组为单位,将每一条数据的所有属性值存储到临近的空间里 以CU(Compress Unit)为单位,将单个属性的所有值存储到临近的空间里 数据主要以CU形式存储在列存主表上,对于被更新的列、小批量插入的数据将被序列化后存储到新设计的Delta表上 类似hstore表,CU文件写入到OBS中 存储行格式数据和列格式数据
数据写入 没有压缩能力,数据按原始状态存储,磁盘空间占用较大 支持压缩,同一列属性值类型相同,压缩效果好。数据写入时能极大节省IO资源与磁盘空间占用 批量插入的数据直接写入CU,具有与列存一致的压缩优势。被更新的列、小批量插入的数据会序列化后压缩。同时定期merge到主表CU 类似hstore表,CU数据数据异步写入OBS 类似hstore,数据按行/列格式同时存入CU,占用空间变大,但得益于压缩能力,空间占用比行存表小
数据更新 数据按行更新,没有CU锁问题,并发更新(update/upsert/delete等)性能好 即使更新单条数据,也要获取整个CU的锁,基本无法支持并发更新(update/upsert/delete等) 彻底解决列存更新的CU锁问题,并发更新(update/upsert/delete等)的性能达到行存的60%以上 OBS相较本地盘读写速度较慢,通过异步写方式加快写入速度 并发更新能力与hstore表相似
数据读取 按行读取,即使只需访问某一列的数据,也需要将一整行的数据取出。非点查性能较差。 按列读取时只需访问该列的CU,再加上CU的压缩优势导致需要占用的IO资源更少,单列读取性能很好。 对于列存主表的数据按列读取,对于被更新的列、小批量插入的数据会反序列化后取出,数据merge到主表后具有与列存一致的数据读取优势。 通过本地盘diskcache能力加速读取 由查询优化器根据实际查询路径选择最优访问方式,通过列存固有的过滤优化能力实现更智能的I/O路径控制,自动选择访问行/列格式数据
优点 并发更新性能好,点查能力强。 查询性能好,磁盘占用空间少。 并发更新性能好,数据MERGE后具有与列存一致的查询性能优势与压缩优势。 扩缩能力强,存储成本低 兼顾点查性能和空间压缩能力,比行存表磁盘占用小。
缺点 占用磁盘空间多,查询性能差。 基本无法支持并发更新。 需要后台常驻线程对HStore表进行merge清理操作。先merge到CU主表再进行清理,与SQL语法中的Merge无关。 OBS相较本地盘读写速度较慢 相比列存表和hstore表,磁盘占用较高
适用场景 更新删除操作频繁的TP事务场景。点查询(基于索引的、返回数据量小的简单查询)。 查询分析为主的AP场景。数据量大,存入后的更新删除操作少。 实时并发入库场景。需要支持高并发的更新入库操作以及高性能的查询效率。 对实时扩展性要求较高或者存储成本敏感的场景 即要求实时入库和大数据查询分析,又要兼顾点查性能的业务。

5. 参考文档

  1. 《GaussDB(DWS)存储引擎:从CU入手优化HStore表》
  2. 《GaussDB(DWS)创建行存表的最佳实践》
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。