Greenplum 清理垃圾、修改存储模式(行列变换) 平滑方法 - 交换数据、交互分区

标签

PostgreSQL , Greenplum , 交换分区 , 清理垃圾 , 存储格式变更


背景

1、在使用Greenplum的过程中,如果业务会经常对数据进行更新,删除,插入,可能导致数据出现膨胀。

《如何检测、清理Greenplum膨胀、垃圾 - 阿里云HybridDB for PG最佳实践》

《Greenplum 列存表(AO表)的膨胀、垃圾检查与空间收缩》

2、用户在建表的时候,存储模式选择不当,但是业务已经运行了一段时间,表里面已经写入了大量的数据。

3、用户在建表的时候,分布键选得不对,但是业务已经运行了一段时间,表里面已经写入了大量的数据。

4、用户在建表的时候表分区做得不对,但是业务已经运行了一段时间,表里面已经写入了大量的数据。

《Greenplum 最佳实践 - 数据分布黄金法则 - 分布列与分区的选择》

5、数据分区在初期选择了行存储,为了提到明细查询的效率。但是到数据冷却后,明细查询的需求下降,更多的是统计查询的需求,那么需要将这样的冷分区的行存储转换成列存储,提高统计的效率。

《Greenplum 行存、列存,堆表、AO表的原理和选择》

6、数据在使用过程中,由于分布键的数据在业务层发生了一些变化,导致了数据存储的倾斜。

《HybridDB PostgreSQL "Sort、Group、distinct 聚合、JOIN" 不惧怕数据倾斜的黑科技和原理 - 多阶段聚合》

《分布式DB(Greenplum)中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践》

以上情况发生时,我们就有必要进行相应的行动:

清理垃圾、调整分布键、分区键、修改存储模式等。

那么,有什么方法可以让这些操作尽量的减少对业务的影响呢?

答案是 交换数据、交换分区。

一、知识点

如何查看存储格式

postgres=# select relname, relkind, relstorage from pg_class  where relkind='r';
            relname            | relkind | relstorage
-------------------------------+---------+------------
 sql_languages                 | r       | h
 sql_packages                  | r       | h
 sql_parts                     | r       | h
 sql_sizing                    | r       | h
 sql_sizing_profiles           | r       | h
 gp_san_configuration          | r       | h

h表示heap 行存储表。

c表示append only column 存储表。

a表示表示append only 行存储表。

postgres=# select relname, relkind, relstorage from pg_class  where relname='a';
 relname | relkind | relstorage
---------+---------+------------
 a       | r       | c
(1 row)  

Time: 0.518 ms

如何查看分布键

1、查看分布键

SELECT attrnums
FROM pg_catalog.gp_distribution_policy t
WHERE localoid = '679926' ;  

 attrnums
----------
 {1}
(1 row)

2、查看分布键名称

SELECT attname FROM pg_attribute
WHERE attrelid = '679926'
AND attnum = '1' ;  

 attname
---------
 uid
(1 row)

如何查看分区

postgres=# select * from pg_partitions where tablename='tbl_pos';

二、单表交换数据

对sales表进行交换。

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;

三、分区表交换分区

对于分区表,Greenplum提供了交换分区的语法

http://greenplum.org/docs/510/ref_guide/sql_commands/ALTER_TABLE.html

EXCHANGE [DEFAULT] PARTITION  

Exchanges another table into the partition hierarchy into the place of an existing partition.
In a multi-level partition design, you can only exchange the lowest level partitions (those that contain data).  

The Greenplum Database server configuration parameter gp_enable_exchange_default_partition controls
availability of the EXCHANGE DEFAULT PARTITION clause. The default value for the parameter is off.
The clause is not available and Greenplum Database returns an error if the clause is specified in an ALTER TABLE command.  

For information about the parameter, see Server Configuration Parameters.  

Warning: Before you exchange the default partition, you must ensure the data in the table to be exchanged,
the new default partition, is valid for the default partition. For example, the data in the new default
partition must not contain data that would be valid in other leaf child partitions of the partitioned table.
Otherwise, queries against the partitioned table with the exchanged default partition that are executed by GPORCA might return incorrect results.  

WITH TABLE table_name - The name of the table you are swapping into the partition design.
You can exchange a table where the table data is stored in the database. For example,
the table is created with the CREATE TABLE command.  

With the EXCHANGE PARTITION clause, you can also exchange a readable external table
(created with the CREATE EXTERNAL TABLE command) into the partition hierarchy in the place
of an existing leaf child partition. If you specify a readable external table,
you must also specify the WITHOUT VALIDATION clause to skip table validation against the
CHECK constraint of the partition you are exchanging.  

Exchanging a leaf child partition with an external table is not supported in these cases:  

The partitioned table is created with the SUBPARTITION clause or if a partition has a subpartition.  

The partitioned table contains a column with a check constraint or a NOT NULL constraint.  

WITH | WITHOUT VALIDATION - Validates that the data in the table matches the CHECK
constraint of the partition you are exchanging. The default is to validate the data against the CHECK constraint.  

Warning: If you specify the WITHOUT VALIDATION clause, you must ensure that the data
in table that you are exchanging for an existing child leaf partition is valid against
the CHECK constraints on the partition. Otherwise, queries against the partitioned table might return incorrect results.  

SET SUBPARTITION TEMPLATE  

Modifies the subpartition template for an existing partition. After a new subpartition
template is set, all new partitions added will have the new subpartition design
(existing partitions are not modified).  

SPLIT DEFAULT PARTITION  

Splits a default partition. Only a range partition can be split, not a list partition.
In a multi-level partition design, you can only split the lowest level default partitions
(those that contain data). Splitting a default partition creates a new partition containing
the values specified and leaves the default partition containing any values that do not match to an existing partition.  

AT - For list partitioned tables, specifies a single list value that should be used as the criteria for the split.  

START - For range partitioned tables, specifies a starting value for the new partition.  

END - For range partitioned tables, specifies an ending value for the new partition.  

INTO - Allows you to specify a name for the new partition. When using the INTO clause
to split a default partition, the second partition name specified should always be that
of the existing default partition. If you do not know the name of the default partition,
you can look it up using the pg_partitions view.  

SPLIT PARTITION  

Splits an existing partition into two partitions. Only a range partition can be split,
not a list partition. In a multi-level partition design, you can only split the lowest
level partitions (those that contain data).  

AT - Specifies a single value that should be used as the criteria for the split.
The partition will be divided into two new partitions with the split value specified
being the starting range for the latter partition.  

INTO - Allows you to specify names for the two new partitions created by the split.  

partition_name  

The given name of a partition.  

FOR (RANK(number))  

For range partitions, the rank of the partition in the range.  

FOR ('value')  

Specifies a partition by declaring a value that falls within the partition boundary specification.
If the value declared with FOR matches to both a partition and one of its subpartitions (for example,
if the value is a date and the table is partitioned by month and then by day), then FOR will operate
on the first level where a match is found (for example, the monthly partition).
If your intent is to operate on a subpartition, you must declare so as follows:
ALTER TABLE name ALTER PARTITION FOR ('2016-10-01') DROP PARTITION FOR ('2016-10-01');

例子

postgres=# select oid from pg_class where relname='tbl_pos';
  oid
--------
 679926
(1 row)  

postgres=# SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhrelid AND i.inhparent = '679926' ORDER BY c.relname;
        oid
-------------------
 tbl_pos_1_prt_p1
 tbl_pos_1_prt_p10
 tbl_pos_1_prt_p2
 tbl_pos_1_prt_p3
 tbl_pos_1_prt_p4
 tbl_pos_1_prt_p5
 tbl_pos_1_prt_p6
 tbl_pos_1_prt_p7
 tbl_pos_1_prt_p8
 tbl_pos_1_prt_p9
(10 rows)  

SELECT attrnums
FROM pg_catalog.gp_distribution_policy t
WHERE localoid = '679926' ;  

 attrnums
----------
 {1}
(1 row)  

SELECT attname FROM pg_attribute
WHERE attrelid = '679926'
AND attnum = '1' ;  

 attname
---------
 uid
(1 row)  

postgres=# select * from pg_partitions where partitiontablename='tbl_pos_1_prt_p5';
-[ RECORD 1 ]------------+--------------------------------------------------------------------------------------------------
schemaname               | postgres
tablename                | tbl_pos
partitionschemaname      | postgres
partitiontablename       | tbl_pos_1_prt_p5
partitionname            | p5
parentpartitiontablename |
parentpartitionname      |
partitiontype            | list
partitionlevel           | 0
partitionrank            |
partitionposition        | 5
partitionlistvalues      | 5::smallint
partitionrangestart      |
partitionstartinclusive  |
partitionrangeend        |
partitionendinclusive    |
partitioneveryclause     |
partitionisdefault       | f
partitionboundary        | PARTITION p5 VALUES(5) WITH (appendonly=true, orientation=row, compresstype=zlib, checksum=false)
parenttablespace         | pg_default
partitiontablespace      | pg_default

查看这个表的膨胀率发现已经膨胀了100%

postgres=# select * from gp_toolkit.__gp_aovisimap_compaction_info('tbl_pos_1_prt_p5'::regclass);
NOTICE:  gp_appendonly_compaction_threshold = 10
 content | datafile | compaction_possible | hidden_tupcount | total_tupcount | percent_hidden
---------+----------+---------------------+-----------------+----------------+----------------
       2 |        1 | t                   |        20833264 |       20833264 |         100.00
       1 |        1 | t                   |        20833546 |       20833546 |         100.00
       6 |        1 | t                   |        20833383 |       20833383 |         100.00
       7 |        1 | t                   |        20833287 |       20833287 |         100.00
       0 |        1 | t                   |        20833180 |       20833180 |         100.00
       5 |        1 | t                   |        20833205 |       20833205 |         100.00
      10 |        1 | t                   |        20833420 |       20833420 |         100.00
      12 |        1 | t                   |        20833193 |       20833193 |         100.00
       4 |        1 | t                   |        20833417 |       20833417 |         100.00
       9 |        1 | t                   |        20833259 |       20833259 |         100.00
       8 |        1 | t                   |        20833455 |       20833455 |         100.00
       3 |        1 | t                   |        20833441 |       20833441 |         100.00
      17 |        1 | t                   |        20833182 |       20833182 |         100.00
      13 |        1 | t                   |        20833436 |       20833436 |         100.00
      15 |        1 | t                   |        20833418 |       20833418 |         100.00
      14 |        1 | t                   |        20833197 |       20833197 |         100.00
      11 |        1 | t                   |        20833306 |       20833306 |         100.00
      16 |        1 | t                   |        20833304 |       20833304 |         100.00
      19 |        1 | t                   |        20833285 |       20833285 |         100.00
      26 |        1 | t                   |        20833215 |       20833215 |         100.00
      25 |        1 | t                   |        20833440 |       20833440 |         100.00
      24 |        1 | t                   |        20833193 |       20833193 |         100.00
      28 |        1 | t                   |        20833394 |       20833394 |         100.00
      30 |        1 | t                   |        20833336 |       20833336 |         100.00
      32 |        1 | t                   |        20833516 |       20833516 |         100.00
      31 |        1 | t                   |        20833313 |       20833313 |         100.00
      35 |        1 | t                   |        20833274 |       20833274 |         100.00
      39 |        1 | t                   |        20833460 |       20833460 |         100.00
      47 |        1 | t                   |        20833269 |       20833269 |         100.00
      34 |        1 | t                   |        20833406 |       20833406 |         100.00
      23 |        1 | t                   |        20833253 |       20833253 |         100.00
      45 |        1 | t                   |        20833305 |       20833305 |         100.00
      42 |        1 | t                   |        20833365 |       20833365 |         100.00
      36 |        1 | t                   |        20833176 |       20833176 |         100.00
      41 |        1 | t                   |        20833301 |       20833301 |         100.00
      20 |        1 | t                   |        20833407 |       20833407 |         100.00
      22 |        1 | t                   |        20833333 |       20833333 |         100.00
      29 |        1 | t                   |        20833259 |       20833259 |         100.00
      37 |        1 | t                   |        20833547 |       20833547 |         100.00
      38 |        1 | t                   |        20833285 |       20833285 |         100.00
      44 |        1 | t                   |        20833413 |       20833413 |         100.00
      40 |        1 | t                   |        20833352 |       20833352 |         100.00
      27 |        1 | t                   |        20833464 |       20833464 |         100.00
      33 |        1 | t                   |        20833272 |       20833272 |         100.00
      43 |        1 | t                   |        20833230 |       20833230 |         100.00
      18 |        1 | t                   |        20833330 |       20833330 |         100.00
      46 |        1 | t                   |        20833467 |       20833467 |         100.00
      21 |        1 | t                   |        20833247 |       20833247 |         100.00
(48 rows)

主备回收空间,新建表,写入数据,交换分区

postgres=# create table tbl_pos_1_prt_p5_exchange(like tbl_pos_1_prt_p5) with (appendonly=true, orientation=row, compresstype=zlib, checksum=false) distributed by (uid);
CREATE TABLE  

postgres=# begin;
BEGIN  

postgres=# lock table tbl_pos_1_prt_p5 in ACCESS EXCLUSIVE mode;
LOCK TABLE  

postgres=# insert into tbl_pos_1_prt_p5_exchange select * from tbl_pos_1_prt_p5;  

-- 注意只调用一次,多次调用会被多次交换(交互偶数次就等于没有改变了)。
postgres=#  alter table tbl_pos alter partition p5 EXCHANGE PARTITION p5 WITH TABLE tbl_pos_1_prt_p5_exchange with VALIDATION;
NOTICE:  exchanged partition "p5" of partition "p5" of relation "tbl_pos" with relation "tbl_pos_1_prt_p5_exchange"
ALTER TABLE  

postgres=# drop table tbl_pos_1_prt_p5_exchange;
DROP TABLE  

postgres=# end;

小结

Greenplum提供给了一种方法:交换数据、交换分区。可以平滑的处理 清理垃圾、调整分布键、分区键、修改存储模式等。

参考

http://greenplum.org/docs/510/ref_guide/sql_commands/ALTER_TABLE.html

http://www.dbaref.com/choosing-the-table-storage-model-in-greenplum

《如何检测、清理Greenplum膨胀、垃圾 - 阿里云HybridDB for PG最佳实践》

《Greenplum 列存表(AO表)的膨胀、垃圾检查与空间收缩》

《Greenplum 行存、列存,堆表、AO表的原理和选择》

《Greenplum 最佳实践 - 数据分布黄金法则 - 分布列与分区的选择》

《HybridDB PostgreSQL "Sort、Group、distinct 聚合、JOIN" 不惧怕数据倾斜的黑科技和原理 - 多阶段聚合》

《分布式DB(Greenplum)中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践》

时间: 2024-07-30 06:18:37

Greenplum 清理垃圾、修改存储模式(行列变换) 平滑方法 - 交换数据、交互分区的相关文章

win7 32位系统怎样设置能使其自动清理垃圾

  很多用户进行了win7 32位系统下载,在使用一段时间之后,就会有不少的系统和程序的垃圾文件.一般很多人都会建议文件夹来存储一些临时的文件,不要的时候及时进行清理,那么有没有好的方法可以让系统自动清理呢?下面就来看看win7 系统自动清理垃圾的具体设置方法吧. 1.打开电脑之后,在桌面上新建一个文本文档,然后直接将其打开,在里面输进去"del 文件夹路径 /q"等字符,然后点击"文件--另存为",如图: 2.这时候就会弹出一个窗口,在里面点击"桌面&q

生产环境中Docker的持久化存储模式

本文讲的是生产环境中Docker的持久化存储模式[编者的话]在生产环境中使用Docker实现持久化存储一直是业界的热点问题,本文从到配置文件.机密材料.数据库.共享数据等方面做了些探讨,文中也谈到了一些需要避免的问题以及尽量将应用设计为无状态服务的原则. 一般看法认为容器对于无状态的应用程序是很好的,但是不适合有持久化数据的有状态应用.如果这是真的,这并不是因为技术不到位,而是因为管理持久化数据和有状态应用程序的模式并不总是为人们所熟知.你面临的挑战很多不是关于持久化状态的,而是如此操作不会影响

云计算设计模式(八)——外部配置存储模式

云计算设计模式(八)--外部配置存储模式 移动配置信息从应用部署包到一个集中位置.这个模式可以提供机会,以便管理和配置数据的控制,以及用于跨应用程序和应用程序实例共享的配置数据. 背景和问题 大多数应用程序运行时环境包括位于应用程序文件夹内的在部署应用程序文件保持配置信息.在某些情况下也能够编辑这些文件来改变该应用程序的行为,它已经被部署之后.然而,在许多情况下,改变配置所需要的应用程序被重新部署,从而导致不可接受的停机时间和额外的管理开销. 本地配置文件还配置限制为单个应用程序,而在某些情况下

Win8系统清理垃圾后无法正常打开应用商店的解决方法

  想要电脑一直保持快捷的网速运行,必须要做的一个操作就是及时清理电脑里的垃圾,因为一些系统垃圾堆积在磁盘中,占据了一部分的空间,就会导致电脑的运行速度变慢,所以及时清理电脑的垃圾是很必要的一件事情.但是最近有用户说他在清理完电脑的垃圾之后,win8系统的应用商店打不开了,这是什么回事呢?清理垃圾和运营商店有什么直接的关系吗?其他一切的功能都能正常运行,只有运营商店打不开,真是奇怪!下面小编就来为大家介绍清理Win8系统后打不开应用商店的解决方法. 操作方法: 1.首先启用win8.1系统的帐户

ASP.NET中的session存储模式运用

在asp.net中的Session存储方式不象asp那样单一,一共提供了三种存储方式,由于最近一个2000多人使用的web软件出现了故障,用户每天早上在某一时刻出现难以登陆现象,接着Session丢值出现,只有重启IIS,或机器.这时程序恢复正常了. 整天都不会出现同样的问题 ,但是第二天依旧!这种现象持续了好几天,我检查了一下日志文件,高峰每秒访问人数大概20人左右,同时大概100多人在线,以后访问人数还会增加,为了解决这个怪问题,先从软件着手,故而三种方式都应用了一番. 打开web.conf

ASP.NET中session存储模式运用

在ASP.NET中的Session存储方式不象asp那样单一,一共提供了三种存储方式,由于最近一个2000多人使用的web软件出现了故障,用户每天早上在某一时刻出现难以登陆现象,接着Session丢值出现,只有重启IIS,或机器.这时程序恢复正常了.整天都不会出现同样的问题 ,但是第二天依旧!这种现象持续了好几天,我检查了一下日志文件,高峰每秒访问人数大概20人左右,同时大概100多人在线,以后访问人数还会增加,为了解决这个怪问题,先从软件着手,故而三种方式都应用了一番. 打开web.confi

C++测试电脑的数据存储模式

相信大家都知道大端存储和小端存储的概念,这在平时,我们一般不用考虑,但是,在某些场合,这些概 念就显得很重要,比如,在 Socket 通信时,我们的电脑是小端存储模式,可是传送数据或者消息给对方电脑 时,恰巧,对方的电脑是大端存储,那么,如果你直接的传输,那么对方解析的肯定就是乱码了,所以,我们 需要在传输数据之前转换成网络顺序. 这篇文章的目的不是解决上述的处理字节顺序的问题,而是, 用C语言实现测试电脑的字节存储顺序. 在C语言中有一种结构--Union,被称为"共用体",它可以像

win8.1系统Winsxs文件夹怎么清理垃圾文件?

win8.1系统Winsxs文件夹怎么清理垃圾文件?   相信很多朋友清理电脑系统垃圾都是借助一些百度卫士.360安全位置.金山卫士等工具来辅助完成,不过尽管借助这些工具可以清理掉系统中的多数垃圾文件,不过也会存在一些死角.在Win7/Win8.1系统中,存在一个冗余更新的WinSxS文件夹,该文件夹中既包含了系统重要文件,也混杂着不少无用的垃圾文件,并且这些垃圾文件也无法通过百度卫士等工具清理,需要通过深度的瘦身来完成,基于此,以下百事网小编为大家带来了Winsxs文件夹瘦身教程. Winsx

金山毒霸如何清理垃圾文件

  金山毒霸清理垃圾文件的方法如下: 百宝箱的"垃圾文件清理"功能,一键点击,即可清除所有垃圾.(备注:64位操作系统下暂不支持功能) 1.单击"全选"按钮可以选中所有扫出的垃圾文件. 2.单击"清除文件"可以清除掉所有选中的文件下的垃圾文件.