greenplum列存

本文深入解析Greenplum数据库的行存储和列存储特性,对比其在OLTP和OLAP场景下的优劣,详细介绍如何创建列存储表,以及如何使用表级和列级压缩提高存储效率。

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)中指定。

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

对于追加优化表,在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-91 是最快的方法但压缩率最低。 1是默认值。9是最慢的方法但压缩率最高。
同上同上QuickLZ压缩:1 – 使用压缩1是默认值。
同上同上RLE_TYPE压缩:1 – 4:1 - 只应用RLE;2 - 应用RLE然后应用zlib压缩级别1;3 - 应用RLE然后应用zlib压缩级别5;4 - 应用RLE然后应用zlib压缩级别91是最快的方法但压缩率最低。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#

<think> 首先,用户的问题是:“我想查找在Greenplum中避免使用索引的方法 请问Greenplum中避免使用索引的方法”。我需要基于提供的引用信息来回答。 用户提到了参考站内引用: - 引用[1]:讨论Greenplum优化,包括用group by改写distinct、使用UNION ALL加GROUP BY改写UNION、使用Greenplum自身的聚合函数和窗口函数。 - 引用[2]:提供Greenplum实用技巧,如并行执行、分区表、索引使用(但提醒避免过度使用索引)、更新统计信息、避免使用函数和子查询、配置资源队。 - 引用[3]:关于Greenplum压缩表索引机制,涉及索引页和如何定位数据。 用户的问题是“避免使用索引的方法”,所以我需要聚焦在为什么和如何避免使用索引。 从引用中提取关键点: - 引用[2]提到:“合理使用索引可以提高查询速度。但是,过度使用索引会导致写入速度下降,因此需要在查询效率和写入效率之间找到平衡。” 这表明索引有缺点,特别是对写入性能的影响。 - 引用[1]建议:“用group by对distinct改写,因为DISTINCT要进行排序操作”和“用UNION ALL加GROUP BY的方式对UNION改写”,这暗示了优化查询以避免某些操作,间接减少索引需求。 - 引用[3]是关于索引机制的,但没有直接提供避免索引的方法。 所以,避免使用索引的方法可能包括: 1. **优化查询**:使用更有效的SQL写法,如引用[1]提到的改写DISTINCT和UNION。 2. **利用分区**:引用[2]提到分区表可以提高查询效率,可能减少对索引的依赖。 3. **使用Greenplum特性**:如引用[1]建议使用Greenplum自身的聚合函数和窗口函数。 4. **避免索引创建**:直接不创建索引,或删除不必要的索引。 5. **其他优化技巧**:如保持统计信息更新(引用[2]),使用并行执行等。 我需要结构化回答: - 回答结构清晰,逐步解决问题。 - 使用中文。 - 行内数学表达式用$...$,独立公式用$$...$$,但这个问题可能不需要数学表达式。 - 生成相关问题。 - 在引用的段落末尾添加引用标识。 步骤: 1. **理解问题**:解释为什么避免索引(如写入性能下降)。 2. **出方法**:基于引用,提供具体方法。 3. **总结**。 4. **生成相关问题**。 确保回答真实可靠:基于提供的引用,不要添加外部知识。 提取具体方法: - 从引用[2]:"避免过度使用索引"。 - 从引用[1]:改写查询,如group by代替distinct。 - 隐含方法:使用分区、并行处理等。 方法表: 1. 优化SQL查询:避免使用DISTINCT和UNION,改用更高效的写法如GROUP BY。 2. 利用分区表:通过分区减少全表扫描需求。 3. 使用Greenplum内置函数:减少自定义函数导致的全表扫描。 4. 避免创建不必要的索引:只在必要时创建索引。 5. 更新统计信息:使用ANALYZE命令,帮助优化器更好地选择执行计划。 6. 配置资源队:管理资源,平衡负载。 在回答中,引用来源: - 例如,提到改写DISTINCT时,添加[^1]。 - 提到避免过度使用索引时,添加[^2]。 生成相关问题: - 基于主题,如:如何优化Greenplum查询性能?索引的优缺点是什么?等。 最终回答结构: - 引言:解释为什么避免索引。 - 方法表:详细说明每个方法。 - 结论。 - 相关问题。 </think>### Greenplum中避免使用索引的方法 在Greenplum分布式数据库中,索引虽然能提升查询速度,但过度使用会导致写入性能下降、储开销增加,并可能引发资源争用问题[^2]。因此,在某些场景下(如高频写入、大数据批量处理),避免索引是优化性能的关键策略。以下基于引用内容,逐步说明避免索引的具体方法。方法主要从查询优化、表设计、资源管理等角度入手,确保系统在减少索引依赖的同时维持高效查询。 #### 1. **优化SQL查询写法,减少排序和扫描操作** - **改写DISTINCT为GROUP BY**: DISTINCT操作通常涉及排序,可能触发索引扫描。改用GROUP BY可以避免不必要的排序,从而减少索引需求。例如: ```sql -- 避免使用: SELECT DISTINCT column FROM table; -- 改写为: SELECT column FROM table GROUP BY column; ``` 这依赖于Greenplum的并行聚合能力,提升效率[^1]。 - **改写UNION为UNION ALL加GROUP BY**: UNION操作会去重并排序,改用UNION ALL结合GROUP BY可以消除排序开销,避免索引调用: ```sql -- 避免使用: SELECT * FROM table1 UNION SELECT * FROM table2; -- 改写为: SELECT * FROM (SELECT * FROM table1 UNION ALL SELECT * FROM table2) AS temp GROUP BY column; ``` 此方法利用Greenplum的分布式计算优势,减少索引依赖[^1]。 - **避免在WHERE子句中使用函数**: 函数调用(如WHERE UPPER(column) = 'value')可能导致全表扫描,强迫索引使用。改用直接比较或预处理数据可避免此问题[^2]。 #### 2. **使用分区表和列存储,降低索引需求** - **采用分区表设计**: 通过按日期、范围等分区数据,查询时只需扫描相关分区而非全表,减少对索引的依赖。例如,按日期分区可高效过滤数据: ```sql CREATE TABLE sales (id int, sale_date date, amount float) DISTRIBUTED BY (id) PARTITION BY RANGE (sale_date); ``` 分区表利用Greenplum的并行执行机制,提升查询速度,无需额外索引[^2]。 - **优先使用列存储压缩表**: Greenplum表(如使用WITH (APPENDONLY=true, ORIENTATION=column))通过压缩和块级扫描优化查询,索引在此场景下效率较低。格式允许直接定位数据块,避免索引页访问(如tid定位机制)[^3]。 #### 3. **利用Greenplum内置函数和资源管理** - **使用内置聚合和窗口函数**: Greenplum提供高效的聚合函数(如SUM() OVER())和窗口函数,处理复杂分析时无需索引支持。例如: ```sql SELECT department, AVG(salary) OVER(PARTITION BY department) FROM employees; ``` 这比自定义查询更高效,减少索引触发[^1]。 - **配置资源队,平衡读写性能**: 通过创建专用资源队,为写入和查询分配不同资源。写入操作时禁用索引创建,查询时依赖并行执行。例如: ```sql CREATE RESOURCE QUEUE write_queue WITH (ACTIVE_STATEMENTS=10); CREATE RESOURCE QUEUE read_queue WITH (ACTIVE_STATEMENTS=20); ``` 这确保写入操作不受索引维护拖累,提升整体吞吐量[^2]。 - **定期更新统计信息**: 使用ANALYZE命令更新表统计信息: ```sql ANALYZE table_name; ``` 帮助优化器选择更有效的执行计划(如顺序扫描而非索引扫描),减少索引必要性[^2]。 #### 4. **直接避免索引创建和维护** - **不创建非关键索引**:仅在频繁查询的上创建索引,其他情况保持无索引状态。 - **删除冗余索引**:定期检查并删除未使用或低效索引: ```sql DROP INDEX index_name; ``` 结合pg_stat_user_indexes视图监控索引使用率[^2]。 #### 总结 避免索引的核心是**优先利用Greenplum的分布式并行处理、分区和内置函数**,而非依赖索引。例如,通过优化查询写法(GROUP BY替代DISTINCT)、分区表设计和资源队配置,可在减少索引的同时维持高性能。在实际应用中,建议监控查询计划(使用EXPLAIN命令),确保方法有效[^1][^2]。平衡查询与写入效率是关键,过度索引会拖慢数据加载,而合理避免可提升系统扩展性[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值