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)中指定:
或者在分区或子分区的with(storage parameter)中指定。
使用压缩(只适用于追加优化表)
• 应用于一整个表的表级压缩。
• 应用到一个指定列的列级压缩。用户可以为不同的列应用不同的列级压缩算法。
下面的表摘要了可用的压缩算法。
注意: QuickLZ压缩在Greenplum数据库的开源版本中不可用。
在为追加优化表选择一种压缩类型和级别时,要考虑这些因素:
• CPU使用。用户的Segment系统必须具有可用的CPU能力来压缩和解压数据。
• 压缩率/磁盘尺寸。小化磁盘尺寸是一个因素,但也要考虑压缩和扫描数据所需的时间和CPU计算能力。要找到能高效压缩数据但不导致过长压缩时间或者过慢扫描率的-优设置。
• 压缩的速度。与zlib比较,QuickLZ压缩通常使用较少的CPU计算能力、能更快地压缩数据且得到较低的压缩率。zlib提供更高的压缩率,但是速度较慢。
• 解压速度/扫描率。压缩的追加优化表的性能取决于硬件、查询调优设置和其他因素。请执行对比测试来判断在用户的环境中的真实性能。
增加列级压缩
• 压缩级别
• 列的块尺寸
CREATE TABLE
、ALTER TABLE
以及CREATE TYPE
命令增加存储指令。下面的表格详细介绍了存储指令的类型以及每一个指令可能的值。
[ 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#