Greenplum既支持行存储,也支持列存储。

行存储优劣分析
Greenplum行存储(堆表)的优势

数据顺序写入BLOCK中,持续写入的情况下,一条记录命中在一个块中,IO开销相对比较小,速度较快。

查询多个字段时,因为记录在一个块中命中,速度较快。

Greenplum行存储(堆表)的劣势

查询少量字段时,也要访问整条记录,造成一定的IO浪费。

行存储的压缩比有限。

行存储适合什么应用场景

行存储适合非常典型的OLTP应用场景。

列存储优劣分析
Greenplum列存储的优势

数据按列存储,压缩比可以做到很高。

当查询少量字段时,扫描的块更少,可以节约IO还能提升效率。

Greenplum列存储的劣势

因为是按列存储的,当需要查询大量字段时,或者查询的记录数偏少时,会造成离散IO较多。

例如查询1条记录的20个列,行存储可能只需要扫描1个块,而列存储至少需要扫描20个块。

由于IO的放大,列存储不适合OLTP的场景,如有大量的更新,查询操作。

列存储适合什么应用场景

列存储适合非常典型的OLAP应用场景,按列做较大范围的聚合分析,或者JOIN分析。

列存和行存的选择

在为一个表决定存储方向模型时,请考虑下列需求:
• 表数据的更新。如果用户会频繁地装载和更新表数据,请选择一个面向行的堆表。面向列的表存储只能用于追加优化表。
• 频繁的INSERT。如果频繁地向表中插入行,请考虑面向行的模型。列存表并未对写操作优化,因为一行的列值必须被写到磁盘上的不同位置。
• 查询中要求的列数。 如果在查询的SELECT列表或者WHERE子句中常常要求所有或者大部分列,请考虑面向行的模型。面向列的表最适合的情况是,查询会聚集一个单一列中的很多值且WHERE或者HAVING谓词也在该聚集列上。例如:

SELECT SUM(salary)...
SELECT AVG(salary)... WHERE salary > 10000

另一种适合面向列的情况是WHERE谓词在一个单一列上并且返回相对较少的行。例如:

SELECT salary, dept ... WHERE state='CA'

• 表中的列数。 在同时要求很多列或者表的行尺寸相对较小时,面向行的存储会更有效。对于具有很多列的表且查询中访问这些列的一个小子集时,面向列的表能够提供更好的查询性能。
• 压缩。 列数据具有相同的数据类型,因此在列存数据上支持存储尺寸优化,但在行存数据上则不支持。例如,很多压缩方案使用临近数据的相似性来进行压缩。不过,临近压缩做得越好,随机访问就会越困难,因为必须解压数据才能读取它们。

创建一个面向列的表

CREATE TABLE命令的WITH子句指定表的存储选项。默认是面向行的堆表。使用面向列的存储的表必须是追加优化表。例如,要创建一个列存表:

=> CREATE TABLE bar (a int, b text) 
    WITH (appendonly=true, orientation=column)
    DISTRIBUTED BY (a);

建表时,在with(storage parameter)中指定:

greenplum 介绍 greenplum优势_greenplum 介绍


或者在分区或子分区的with(storage parameter)中指定。

使用压缩(只适用于追加优化表)

对于追加优化表,在Greenplum数据库中有两种类型的库内压缩可用:
• 应用于一整个表的表级压缩。
• 应用到一个指定列的列级压缩。用户可以为不同的列应用不同的列级压缩算法。
下面的表摘要了可用的压缩算法。

表方向

可用的压缩类型

支持的算法



ZLIB以及 QUICKLZ


列和表

RLE_TYPE、ZLIB以及 QUICKLZ

注意: QuickLZ压缩在Greenplum数据库的开源版本中不可用。

在为追加优化表选择一种压缩类型和级别时,要考虑这些因素:
• CPU使用。用户的Segment系统必须具有可用的CPU能力来压缩和解压数据。
• 压缩率/磁盘尺寸。最小化磁盘尺寸是一个因素,但也要考虑压缩和扫描数据所需的时间和CPU计算能力。要找到能高效压缩数据但不导致过长压缩时间或者过慢扫描率的最优设置。
• 压缩的速度。与zlib比较,QuickLZ压缩通常使用较少的CPU计算能力、能更快地压缩数据且得到较低的压缩率。zlib提供更高的压缩率,但是速度较慢。
• 解压速度/扫描率。压缩的追加优化表的性能取决于硬件、查询调优设置和其他因素。请执行对比测试来判断在用户的环境中的真实性能。

增加列级压缩

用户可以为列存追加优化表的列增加下列存储指令:
• 压缩类型
• 压缩级别
• 列的块尺寸
使用CREATE TABLEALTER TABLE以及CREATE TYPE命令增加存储指令。
下面的表格详细介绍了存储指令的类型以及每一个指令可能的值。

名称

定义


注释

COMPRESSTYPE

压缩的类型

zlib: 缩小算法;quicklz: 快速压缩;RLE_TYPE: 游程编码;none: 无压缩

值不区分大小写

COMPRESSLEVEL

压缩级别

zlib 压缩: 1-9

1 是最快的方法但压缩率最低。 1是默认值。9是最慢的方法但压缩率最高。

同上

同上

QuickLZ压缩:1 – 使用压缩

1是默认值。

同上

同上

RLE_TYPE压缩:1 – 4:1 - 只应用RLE;2 - 应用RLE然后应用zlib压缩级别1;3 - 应用RLE然后应用zlib压缩级别5;4 - 应用RLE然后应用zlib压缩级别9

1是最快的方法但压缩率最低。4是最慢的方法但压缩率最高。1是默认值。

BLOCKSIZE

表中每一块的以字节计的尺寸

8192 – 2097152 该值必须是8192的倍数。

下面是增加存储指令的格式。

[ ENCODING ( storage_directive [,…] ) ]

其中单词ENCODING是必需的并且存储指令有三个部分:
• 指令的名称
• 一个等号
• 参数
多个存储指令用逗号分隔。如下面的CREATE TABLE子句所示,可以把一个存储指令应用到单一列或者把它作为所有列的默认指令。
一般用法:

column_name data_type ENCODING ( storage_directive [, … ] ), …  
COLUMN column_name ENCODING ( storage_directive [, … ] ), … 
DEFAULT COLUMN ENCODING ( storage_directive [, … ] )

示例:

C1 char ENCODING (compresstype=quicklz, blocksize=65536) 
COLUMN C1 ENCODING (compresstype=zlib, compresslevel=6, blocksize=65536)
DEFAULT COLUMN ENCODING (compresstype=quicklz)
压缩设置的优先级

列压缩设置从表级继承到分区级,再到子分区级。最低级别上的设置优先。
• 在表级别指定的列压缩设置覆盖整个表的任何压缩设置。
• 为分区指定的列压缩设置覆盖在列或者表级指定的任何压缩设置。
• 为子分区指定的列压缩设置覆盖在分区、列或者表级别指定的任何压缩设置。
• 当一个ENCODING子句与一个 WITH子句冲突时,ENCODING子句比WITH子句具有更高的优先级。

修改表的存储模型

表存储、压缩和存储方向只能在创建时声明。要改变存储模型,用户必须用正确的存储选项创建一个表,再把原始表的数据载入到新表中,接着删除原始表并且把新表重命名为原始表的名称。用户还必须重新授权原始表上有的权限。例如:

CREATE TABLE sales2 (LIKE sales) 
WITH (appendonly=true, compresstype=quicklz, 
      compresslevel=1, orientation=column);
INSERT INTO sales2 SELECT * FROM sales;
DROP TABLE sales;
ALTER TABLE sales2 RENAME TO sales;
GRANT ALL PRIVILEGES ON sales TO admin;
GRANT SELECT ON sales TO guest;

参考:
1.https://gp-docs-cn.github.io/docs/admin_guide/ddl/ddl-storage.html#top 2.https://yq.aliyun.com/articles/59132#