1.行存表/列存表说明
1.1 概念
openGauss支持行列混合存储。
- 行存表: 默认创建表的类型。数据按行进行存储,即一行数据紧挨着存储。行存表支持完整的增删改查。适用于对数据需要经常更新的TP场景。
- 列存表: 数据按列进行存储,即一列所有数据紧挨着存储。单列查询IO小,比行存表占用更少的存储空间。适合数据批量插入、更新较少和以查询为主统计分析类的AP场景。列存表不适合点查询,insert插入单条记录性能差。
行、列存储模型各有优劣,建议根据实际情况选择:
- 更新频繁程度:数据如果频繁更新,选择行存表。
- 插入频繁程度:频繁的少量插入,选择行存表。一次插入大批量数据,选择列存表。
- 表的列数:表的列数很多,选择列存表。
- 查询的列数:如果每次查询时,只涉及了表的少数(<50%总列数)几个列,选择列存表。
- 压缩率:列存表比行存表压缩率高。但高压缩率会消耗更多的CPU资源。
1.2 优缺点
行存表:
- 优点:数据被保存在一起。INSERT/UPDATE容易。
2 .缺点:选择(Selection)时即使只涉及某几列,所有数据也都会被读取。
列存表:
优点:
1)查询时只有涉及到的列会被读取。
2)投影(Projection)很高效。
3)任何列都能作为索引。缺点:
1) 选择完成时,被选择的列要重新组装。
2) INSERT/UPDATE比较麻烦。
1.3 适用场景
一般情况下,如果表的字段比较多(大宽表),查询中涉及到的列不多的情况下,适合列存储。如果表的字段个数比较少,查询大部分字段,那么选择行存储比较好。
行存适用场景:
- 点查询(返回记录少,基于索引的简单查询)。
- 增、删、改操作较多的场景。
列存适用场景:
- 统计分析类查询(关联、分组操作较多的场景)。
- 即席查询(查询条件不确定,行存表扫描难以使用索引)。
1.4 操作示例
默认创建行存表:
openGauss=# create table ustc(id int);
CREATE TABLE
openGauss=# /dt+ ustc
List of relations
Schema | Name | Type | Owner | Size | Storage | Description
--------+------+-------+-------+---------+----------------------------------+-------------
public | ustc | table | omm | 0 bytes | {orientation=row,compression=no} |
(1 row)
openGauss=#
创建列存表:
openGauss=# create table ustc2(id int) with(ORIENTATION = COLUMN);
CREATE TABLE
openGauss=# /dt+ ustc2
List of relations
Schema | Name | Type | Owner | Size | Storage | Description
--------+-------+-------+-------+-------+--------------------------------------+-------------
public | ustc2 | table | omm | 16 kB | {orientation=column,compression=low} |
(1 row)
关于行存和列存的压缩率和性能,这里不进行测试。
2.向量化执行引擎
2.1 向量化执行引擎说明
openGauss数据库支持 行执行引擎 和 向量化执行引擎,分别对应行存表和列存表。
- 一次一个batch,读取更多数据,节省IO。
- batch中记录较多,CPU cache命中率提升。
- Pipeline模式执行,函数调用次数少。
- 一次处理一批数据,效率高。
openGauss数据库对分析类的复杂查询能够获得更好的查询性能,但列存表在数据插入和数据更新上表现不佳,所以存在数据频繁插入和更新的业务无法使用列存表。
为了提升行存表在分析类的复杂查询上的查询性能,openGauss数据库提供行存表使用向量化执行引擎的能力。通过设置GUC参数try_vector_engine_strategy,可以将包含行存表的查询语句转换为向量化执行计划执行。
行存表转换为向量化执行引擎执行不是对所有的查询场景都适用。参考向量化引擎的优势,如果查询语句中包含表达式计算、多表join、聚集等操作时,通过转换为向量化执行能够获得性能提升。从原理上分析,行存表转换为向量化执行,会产生转换的开销,导致性能下降。而上述操作的表达式计算、join操作、聚集操作转换为向量化执行之后,能够获得获得性能提升。所以查询转换为向量化执行后,性能是否提升,取决于查询转换为向量化之后获得的性能提升能否高于转换产生的性能开销。
以TPCH Q1为例,使用行执行引擎时,扫描算子的执行时间为405210ms,聚集操作的执行时间为2618964ms;而转换为向量化执行引擎后,扫描算子(SeqScan + VectorAdapter)的执行时间为470840ms,聚集操作的执行时间为212384ms,所以查询能够获得性能提升。
TPCH Q1 行执行引擎执行计划:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=43539570.49..43539570.50 rows=6 width=260) (actual time=3024174.439..3024174.439 rows=4 loops=1)
Sort Key: l_returnflag, l_linestatus
Sort Method: quicksort Memory: 25kB
-> HashAggregate (cost=43539570.30..43539570.41 rows=6 width=260) (actual time=3024174.396..3024174.403 rows=4 loops=1)
Group By Key: l_returnflag, l_linestatus
-> Seq Scan on lineitem (cost=0.00..19904554.46 rows=590875396 width=28) (actual time=0.016..405210.038 rows=596140342 loops=1)
Filter: (l_shipdate <= '1998-10-01 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 3897560
Total runtime: 3024174.578 ms
(9 rows)
TPCH Q1 向量化执行引擎执行计划:
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
Row Adapter (cost=43825808.18..43825808.18 rows=6 width=298) (actual time=683224.925..683224.927 rows=4 loops=1)
-> Vector Sort (cost=43825808.16..43825808.18 rows=6 width=298) (actual time=683224.919..683224.919 rows=4 loops=1)
Sort Key: l_returnflag, l_linestatus
Sort Method: quicksort Memory: 3kB
-> Vector Sonic Hash Aggregate (cost=43825807.98..43825808.08 rows=6 width=298) (actual time=683224.837..683224.837 rows=4 loops=1)
Group By Key: l_returnflag, l_linestatus
-> Vector Adapter(type: BATCH MODE) (cost=19966853.54..19966853.54 rows=596473861 width=66) (actual time=0.982..470840.274 rows=596140342 loops=1)
Filter: (l_shipdate <= '1998-10-01 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 3897560
-> Seq Scan on lineitem (cost=0.00..19966853.54 rows=596473861 width=66) (actual time=0.364..199301.737 rows=600037902 loops=1)
Total runtime: 683225.564 ms
(11 rows)
2.2 配置参数
openGauss 5.0.0 参数 查看 与 修改
https://www.cndba.cn/dave/article/116536
try_vector_engine_strategy
设置行存表走向量化执行引擎的策略。通过设置该参数,可以使包含行存表的查询可以转换为向量化的执行计划执行计算,从而提升类AP场景的复杂查询的执行性能。
该参数属于USERSET类型参数,可以直接修改,参数可以设置为如下值啊:
- off,为默认取值,表示关闭本功能,即行存表不会转换为向量的执行计划执行。
- force,表示只要查询中不包含向量化引擎不支持的类型或者表达式,则不论查询的基表为行存表、列存表,还是行列混合存储的,强制将查询转换为向量化的执行计划执行计算。在这种情况下,针对不同的查询场景可能出现性能下降。
- optimal,表示在force的基础上,由优化器根据查询的复杂度进行选择是否将查询语句转换为向量化的执行计划,尽可能避免转换为向量化的执行计划后出现性能下降。
[dave@www.cndba.cn ~]$ gsql -p 15500 -d postgres -U omm -W omm@123456 -r
gsql ((openGauss 5.0.0 build a07d57c3) compiled at 2023-03-29 03:07:56 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.
openGauss=# select name,setting,context,source from pg_settings where name like 'try_vector_engine_strategy';
name | setting | context | source
----------------------------+---------+---------+---------
try_vector_engine_strategy | off | user | default
(1 row)
openGauss=#
[dave@www.cndba.cn ~]$ gs_guc set -N all -I all -c "try_vector_engine_strategy=optimal"
The gs_guc run with the following arguments: [gs_guc -N all -I all -c try_vector_engine_strategy=optimal set ].
Begin to perform the total nodes: 3.
Popen count is 3, Popen success count is 3, Popen failure count is 0.
Begin to perform gs_guc for datanodes.
Command count is 3, Command success count is 3, Command failure count is 0.
Total instances: 3. Failed instances: 0.
ALL: Success to perform gs_guc!
[dave@www.cndba.cn ~]$
openGauss=# alter database postgres set try_vector_engine_strategy=optimal;
ALTER DATABASE
openGauss=# select name,setting,context,source from pg_settings where name like 'try_vector_engine_strategy';
name | setting | context | source
----------------------------+---------+---------+---------
try_vector_engine_strategy | off | user | default
(1 row)
修改并没有生效,我们重启库后,生效:
[dave@www.cndba.cn ~]$ gs_om -t restart
Stopping cluster.
=========================================
Successfully stopped cluster.
=========================================
End stop cluster.
Starting cluster.
======================================================================
Successfully started primary instance. Wait for standby instance.
======================================================================
.
Successfully started cluster.
======================================================================
cluster_state : Normal
redistributing : No
node_count : 3
Datanode State
primary : 1
standby : 2
secondary : 0
cascade_standby : 0
building : 0
abnormal : 0
down : 0
Successfully started cluster.
[dave@www.cndba.cn ~]$ gs_om -t status --detail
[ CMServer State ]
node node_ip instance state
-------------------------------------------------------------------------------
1 oracle 192.168.56.105 1 /data/openGauss/data/cmserver/cm_server Standby
2 oracle2 192.168.56.106 2 /data/openGauss/data/cmserver/cm_server Primary
3 oracle3 192.168.56.107 3 /data/openGauss/data/cmserver/cm_server Standby
[ Cluster State ]
cluster_state : Normal
redistributing : No
balanced : Yes
current_az : AZ_ALL
[ Datanode State ]
node node_ip instance state
---------------------------------------------------------------------------------
1 oracle 192.168.56.105 6001 /data/openGauss/install/data/dn P Primary Normal
2 oracle2 192.168.56.106 6002 /data/openGauss/install/data/dn S Standby Normal
3 oracle3 192.168.56.107 6003 /data/openGauss/install/data/dn S Standby Normal
[dave@www.cndba.cn ~]$
openGauss=# select name,setting,context,source from pg_settings where name like 'try_vector_engine_strategy';
name | setting | context | source
----------------------------+---------+---------+----------
try_vector_engine_strategy | optimal | user | database
(1 row)
openGauss=#
版权声明:本文为博主原创文章,未经博主允许不得转载。