GaussDB(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. 参考文档
- 点赞
- 收藏
- 关注作者
评论(0)