Greenplum入門——基礎知識、安裝、常用函數
本文為博主在學習Greenplum時閱讀的《Greenplum企業應用實戰》時的筆記,對書中章節的知識要點進行了歸納和梳理。有興趣的同學可以找原書學習下。如果認為文中內容涉嫌侵權請及時聯系博主刪除文章。
軟件安裝及數據庫初始化
Greenplum架構
Master主機與Segment主機的職責
Master
- 建立與客戶端的會話連接和管理
- SQL的解析並形成分布式的執行計划
- 將生成好的執行計划分發到每個Segment上執行
- 收集Segment的執行結果
- 不存儲業務數據,只存儲數據字典
- 可以一主一備,分布在兩台機器上
- 為了提高性能,最好單獨占用一台機器
Segment
- 業務數據的存儲和存取
- 執行由Master分發的SQL語句
- 對於Master來說,每個Segment都是對等的,負責對應數據的存儲和計算
- 每一台機器上可以配置一到多個Segment
- 由於每個Segment都是對等的,建議蠶蛹相同的及其配置
- Segment分primary和mirror兩種,一般交錯的存放在子節點上
Master和Segment都是一個單獨的PostgreSQL數據庫。每一個都有自己單獨的一套元數據字典。Master節點一般也叫主節點,Segment叫做數據節點。
為了實現高可用,每個Segment都有對應的備節點 Mirror Segment分別存在與不同的機器上。
Client一般只能與Master節點進行交互,Client將SQL發給Master,然后Master對SQL進行分析后再講其分配給所有的Segment進行操作。
環境搭建
操作系統
Greenplum沒有Windows版本,只能安裝在類UNIX的操作系統上
數據庫存儲
Greenplumn極度消耗IO資源,所以對存儲的要求比較高。
文件系統的選擇上,Linux下建議使用XFS,Solaris建議使用ZFS,對於Raid根據需求選擇硬Raid活軟Raid,如果需要更大孔家,建議使用Raid5,如果對性能要求更高,可選擇Raid1+0.
網絡
配置/etc/hosts時,習慣將Master機器叫做mdw,將Segment機器叫做sdw
創建用戶及用戶組
將原有用戶刪除
#groupdel gpadmin #userdel gpadmin
- 1
- 2
安裝
1.安裝數據庫軟件
創建新的用戶和用戶組
#groupadd -g 530 gpadmin #useradd -g 530 -u 530 -m -d /home/gpadmin -s /bin/bash gpadmin
- 1
- 2
對文件夾賦權,為新用戶創建密碼
#chown -R gpadmin:gpadmin /home/gpadmin/ #passwd gpadmin Changing password for user gpadmin. New UNIX password: Retype new UNIX password:
- 1
- 2
- 3
- 4
- 5
執行unzip命令解壓安裝文件
unzip greenplum-db-4.1.1.1-build-1-RHEL5-x86_64.zip
- 1
為Greenplum軟件創建安裝目錄,並且賦給gpadmin用戶權限
mkdir /opt/greenplum chown -R gadmin:gpadmin /opt/greenplum
- 1
- 2
安裝
./greenplum-db-4.1.1.1-build-1-RHEL5-x86_64.bin
- 1
安裝完成后Greenplum的環境變量已經在greenplum_path.sh中設置了。
引用環境變量配置
source /opt/greenplum/greenplum-db/greenplum_path.sh
- 1
2.配置hostlist
[gpadmin@dw-greenplum01 ]$ cat hostlist mdw sdw1 sdw2 sdw3
- 1
- 2
- 3
- 4
- 5
seg_hosts只保存segment節點的hostname
[gpadmin@dw-greenplum-1 conf]$ cat seg_hosts sdw1 sdw2 sdw3
- 1
- 2
- 3
- 4
3.使用gpssh-exkeys打通所有服務器
使用gpssh-exkeys將所有機器的通道打開,這樣就不用輸入密碼使登陸在每台機器之間跳轉了
[gpadmin@dw-greenplum-1 conf]$ gpssh-exkeys -f hostlist
- 1
打通所有機器通道后,就可以使用gpssh命令對所有機器進行批量操作了
4.將軟件分發到每一台機器上
將安裝后的文件打包
tar -cf gp4.1.tar greenplum-db-4.1.1.1/
- 1
使用gpscp命令將這個文件復制到每一台機器上
gpscp -f /home/gpadmin/conf/hostlist gp4.1.tar =:/opt/greenplum
- 1
使用gpssh命令批量解壓文件包
=> cd /opt/greenplum => tar -xf gp4.1.tar
- 1
- 2
- 3
創建數據庫數據目錄
- Master目錄
=> mkdir -p /home/gpadmin/gpdata/gpmaster
- 1
- Primary節點目錄
=> mkdir -p /home/gpadmin/gpdata/gpdatap1 => mkdir -p /home/gpadmin/gpdata/gpdatap2
- 1
- 2
- Mirror節點目錄
=> mkdir -p /home/gpadmin/gpdata/gpdatam1 => mkdir -p /home/gpadmin/gpdata/gpdatam2
- 1
- 2
- 3
Gpmaster目錄保存Master的數據,么個機器上的gpdatap1、gpdatap2分別對應這個機器上的兩個主數據節點目錄,gpdatam1、gpdatam2對應備數據節點目錄
5.配置~/.bash_profile
修改環境變量
添加內容
source /opt/greenplum/greenplum-db/greenplum_path.sh export MASTER_DATA_DIRECTORY=/home/gpadmin/gpdata/gpmaster/gpseg-1 export PGPORT=2345 export PGDATABASE=testDB
- 1
- 2
- 3
- 4
6.初始化Greenplum的配置文件
配置文件的模板可以在$GPHOME/docs/cli_help/gpconfigs/目錄下找到。gpinitsystem_config文件是初始化Greenplum的模板,在這個模板中,Mirror Segment的配置都被注釋掉了,模板中基本初始化數據庫的參數都是有的。
# 數據庫的代號 ARRAY_NAME = "Greenplum" MACHINE_LIST_FILE=/home/gpadmin/conf/seg_hosts # Segment的名稱前綴 SEG_PREFIX=gpseg # Primary Segment騎士的端口號 PORT_BASE=33000 # 指定Primary Segment的數據目錄 declare -a DATA_DIRECTORY=(/home/gpadmin/gpdata/gpdatap1 /home/gpadmin/gpdata/gpdatap2) # Master 所在機器的Hostname MASTER_HOSTNAME=mdw # 指定Master的數據目錄 MASTER_DIRECTORY=/home/gpadmin/gpdata/gpmster # Master的端口 MASTER_PORT=2345 # Bash版本 TRUSTED_SHELL=/usr/bin/ssh # 字符集 ENCODING = UNICODE # Mirror Segment起始的端口號 MIRROR_PORT_BASE=43000 # Primary Segment 主備同步的起始端口號 REPLICATION_PORT_BASE=34000 #Mirror Segment主備同步的起始端口號 MIRROR_REPLICATION_PORT_BASE=44000 # Mirror Segment的數據目錄 declare -a MIRROR_DATA_DIRECTORY=(/home/gpadmin/gpdata/gpdatam1 /home/gpadmin/gpdata/gpdatam2)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
7.初始化數據庫
使用gpinitsystem腳本初始化數據庫
gpinitsystem -c initgp_config -s sdw3
- 1
登陸Greenplum默認的數據庫postgres
[gpadmin@dw-greenplum-1 ~]$ psql -d postgres
- 1
創建數據庫
createdb testDB -E utf-8
- 1
沒有設置PGDATABASE環境變量時,使用psql進行登錄,默認的數據庫與操作系統用戶名一致
設置環境變量,修改默認登陸數據庫
[gpadmin@dw-greenplum01 ~]$ export PGDATABASE=testDB [gpadmin@dw-greenplum01 ~]$ psql
- 1
- 2
數據庫啟動與關閉
1.啟動數據庫
Greenplum提供腳本來管理數據庫,gpstart是啟動數據庫的腳本,可以用gpstart -help查看幫助
一般使用
gpstart -a
- 1
直接啟動數據庫
2.關閉數據庫
gpstop是關閉數據庫的腳本
一般使用
gpstop -a
- 1
直接關閉數據庫
暢游Greenplum
訪問Greenplum
1.psql
psql是Greenplum/PostgreSQL默認的客戶端
使用psql遠程連接
admin@test1:、home/admin>psql -h 10.20.151.7 -p 2345 -d testDB -U gpadmin
- 1
Greenplum有權限控制,並不是所有的及其都可以連接到數據庫。如果有其他計算機要登陸Greenplum,先為數據庫用戶gpadmin創建一個密碼,然后在pg_hba.conf文件中增加客戶端機器的權限配置,就可以成功登陸了。
testDB=# alter role gpadmin with password 'gpadmin';
- 1
- 2
在$MASTER_DATA_DIRECTORY/pg_hba.conf文件中增加
host testDB gpadmin 10.20.151.1/32 md5
- 1
使配置生效
gpstop -u
- 1
2.pgAdmin
…
基本語法
1.獲取語法介紹
可以使用 \h 查看GreenPlum支持的所有語法
在psql中使用\h command
testDB=# \h create view
- 1
2.CREATE TABLE
與其他數據庫不同的地方:
- 在Greenplum中建表時需要指定表的分布鍵
- 如果表需要用某個字段分區,可以通過partition by將表建成分區表
- 可以使用like操作創建與like的表一樣結構的表,功能類似 create table t1 as select * from t2 limit 0
- 可以使用inherits實現表的繼承
CREATE [[GLOBAL|LOCAL] {TEMPORARY|TEMP}] TABLE table_name (
[
{
column_name data_type [DEFAULT default_expr]
[column_constraint [...]] | table_constraint | LIKE ohter_table [{INCLUDING|EXCLUDING} {DEFAULTS|CONSTRAINTS} ...] } [,...] ]... ) [INHERITS (parent_table [,...])] [WITH (storage_parameter=value [,...]) [ON COMMIT {PRESERVE ROWS|DELETE ROWS|DROP}] [TABLESPACE tablespace] [DISTRIBUTED BY (column,[...]) | DISTRIBUTED RANDOMLY] [PARTITION BY partition_type (column) [SUBPARTITION BY partition_type (column)] [SUBPARTITION TEMPLATE (template_spec)] [...] (partition_spec) |[SUBPARTITION BY partition_type(column)] [...] (partition_spec) [(subpartition_spec [(...)] )] ]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
Greenplum是一個分布式數據庫,有兩種數據分布策略:
1. Hash分布。指定一個活多個分布鍵,計算hash值,並且通過hash值路由到特定的Segment節點上,語法為Distributed by(…)。如果不指定分布鍵,默認將第一個字段作為分布鍵。
2. 隨機分布,也叫平均分布。數據隨機分散在每一個節點中,這樣無論數據是什么內容,都可以平均分布在每個節點上,==但是在執行SQL的過程中,關聯等操作都需要將數據重分布,性能較差。==語法為在表字段定義的后面加上Distributed randomly
采用隨機分布策略的表默認將主鍵或唯一鍵作為分布鍵,因為每一個Segment都是一個單一的數據庫,單個的數據庫可以保證唯一性,多個數據庫節點就無法保證全局的跨庫唯一性,故只能按照唯一鍵分布,同一個值的數據都在一個節點上,以此來保證唯一性。
==如果指定的分布鍵與主鍵不一樣,那么分布鍵會被更改為主鍵。==
使用like創建的表,只是表結構會與原表一模一樣,表的一些特殊屬性並不會一樣,例如亞索、只增 appendonly等。如果不指定分布鍵,則默認分布鍵與原表相同。
3.SELECT
SELECT語句的基本語法跟其他數據庫類似,也有自己的一些特性,例如分頁采用offset加limit操作
SELECT可以不用指定From字句,如執行函數、進行一些簡單的科學計算等。
如果不加order by字句,查詢的結果中,數據的順序是不能夠保證的。
4.create table as 與 select into
create table as 與 select into 有一樣的功能,都可以使表根據直接執行SELECT的結果創建出一個新的表,這個在臨時分析數據的時候十分方便。例如,在創建一個表的時候如果默認不指定分布鍵,那么Greenplum根據執行SELECT得到的結果集來選擇,不用再次分重分布數據的字段作為表的分布鍵。
也可以手動加入distributed關鍵字,指定分布鍵,這樣數據就會根據指定分布鍵再建表。
select into的語法比create table as更簡單,雖然功能一樣,但是執行select into不能指定分布鍵,只能使用默認的分布鍵。
5.explain
explain用於查詢一個表的執行計划。
testDB=# explain select * from test1 x,test2 y where x.id=y.id;
- 1
6.insert/update/delete
insert
在執行insert語句的時候,注意分布鍵不要為空,否則分布鍵默認會變成null,數據都被保存在一個節點上,造成數據分布不均。
可以批量操作
testDB=# insert into test001 values(100,'tom'),(101,'lily');
- 1
update
不能批量對分布鍵執行update,因為對分布鍵執行update需要將數據重分布,Greenplum暫時不支持這個功能。
delete
Greenplum 3.x版本中,如果delete操作涉及子查詢,並且子查詢的結果還會涉及數據重分布,這樣的刪除語句會報錯。
對整張表執行Delete較慢,有此需求時建議使用truncate
7.truncate
與oracle一樣,執行truncate直接刪除表的物理文件,然后創建新的數據文件。truncate操作比delete操作在性能上有非常大的提升,當前如果有sql正在操作這張表,那么truncate操作會被鎖住,知道表上面的所有鎖被釋放
常用數據類型
Greenplum的數據類型基本與PostgreSQL的一樣。
1.數值類型
類型名稱 | 存儲空間 | 描述 | 范圍 |
---|---|---|---|
smallint | 2字節 | 小范圍整數 | -32 768~+32 767 |
integer | 4字節 | 常用的整數 | -2 147 483 648~+2 147 483 647 |
bigint | 8字節 | 大范圍的整數 | -9 223 372 036 854 775 808~9 223 372 036 854 775 807 |
decimal | 變長 | 用戶聲明精度,精確 | 無限制 |
numeric | 變長 | 用戶聲明精度,精確 | 無限制 |
real | 4字節 | 變精度,不精確 | 6位十進制數字精度 |
double precision | 8字節 | 變精度,不精確 | 15位十進制數字精度 |
serial | 4字節 | 自增整數 | 1 - 2 147 483 647 |
bigserial | 8字節 | 大范圍的自增整數 | 1 - 9 223 372 036 854 775 807 |
2.字符類型
類型名稱 | 描述 |
---|---|
character varying(n),varchar(n) | 變長,有長度限制 |
character(n),char(n) | 定長,不足補空白 |
text | 變長,無長度限制 |
3.時間類型
類型名稱 | 存儲空間 | 描述 | 最低值 | 最高值 | 時間精度 |
---|---|---|---|---|---|
timestamp[(p)][without time zone] | 8字節 | 日期和時間 | 4713BC | 5874897AD | 1毫秒 |
timestamp[(p)] with time zone | 8字節 | 日期和時間,帶時區 | 4713BC | 5874897AD | 1毫秒 |
interval[(p)] | 12字節 | 時間間隔 | -178 000 000年 | 178 000 000年 | 1毫秒 |
date | 4字節 | 只用於表示日期 | 4713BC | 5 874 897AD | 1天 |
time[(p)][without time zone] | 8字節 | 只用於表示一日內的時間 | 00:00:00 | 24:00:00 | 1毫秒 |
time[(p)] with time zone | 12字節 | 只用於表示一日內時間,帶時區 | 00:00:00+1459 | 24:00:00-1459 | 1毫秒 |
常用函數
字符串函數
函數 | 返回類型 | 描述 | 例子 | 結果 |
---|---|---|---|---|
string||string | text | 字符串連接 | ||
length(string) | int | string中字符的數目 | length(‘jose’) | 4 |
position(substring in string) | int | 指定的子字符串的位置 | position(‘om’in’Tomas’) | 3 |
substring(string[from int][for int]) | text | 抽取子字符串 | substring(‘Thomas’from 2 for 3) | hom |
trim([leading|trailing|both][characters]from string) | text | 從字符串string的開頭/結尾/兩邊刪除只包含characters中字符(默認是空白)的最長的字符串 | trim(both ‘x’ from ‘xTomxx’) | Tom |
lower(string) | text | 把字符串轉化為小寫 | ||
upper(string) | text | 把字符串轉化為大寫 | ||
overlay(string placing string from int [for int]) | text | 替換子字符串 | overlay(‘Txxxxas’ placing ‘hom’ from 2 for 4) | Thomas |
replace(string text,from text,to text) | text | 把字符串string中出現的所有子字符串from替換成子字符串to | replace(‘abcdefabcdef’,’cd,’XX’) | abXXefabXXef |
split_part(string text, delimiter text,filed int) | text | 根據delimiter分隔string返回生成的第field個子字符串(1開始) | split_part(‘abc|def|ghi’,’|’,2) | def |
時間函數
函數 | 返回類型 | 描述 | 例子 | 結果 |
---|---|---|---|---|
age(timestamp,timestamp) | interval | 減去參數后的”符號化”結果 | age(timestamp’2001-04-10’,timestamp’1957-06-13) | 43 years 9 mons 27 das |
age(timestam) | interval | 從current_date減去參數中的日期 | age(timestam’1957-06-13) | - |
current_date | date | 當前的日期 | - | - |
current_time | time with time zone | 當日時間 | - | - |
current_timestamp | timestamp with time zone | 當前事務開始時的事件戳 | - | - |
date_part(text,timestamp) | double precision | 獲取子域(等效於extract) | date_part(‘hour’,timestamp’2001-02-16 20:38:40) | 20 |
date_trunc(text,timestamp) | timestamp | 截斷成指定的精度 | date_trunc(‘hour’,timestamp ‘2001-02-16 20:38:40’) | 2001/2/16 20:00 |
extract(field from timestamp) | double precision | 獲取子域 | (同date_part) | (同date_part) |
now() | timestampe with time zone | 當前事務開始的時間戳 | - | - |
使用interval類型可以直接對事件類型進行計算,用來計算時間的加減
數值計算函數
函數 | 返回類型 | 描述 | 例子 | 結果 |
---|---|---|---|---|
abs(x) | (與x相同) | 絕對值 | - | - |
ceil(dp或numeric)\ceiling | (與輸入相同) | 不小於參數的最小整數 | - | - |
exp(dp或numeric) | (與輸入相同) | 自然指數 | - | - |
ln(dp或numeric) | (與輸入相同) | 自然對數 | - | - |
log(dp或numeric) | (與輸入相同) | 以10 為底的對數 | - | - |
log(b numeric,x numeric) | numeric | 以b為底的對數 | - | - |
mod(y,x) | (與參數類型相同) | y/x的余數 | - | - |
pi() | dp | π | - | - |
power(a numeric,b numeric) | numeric | a的b次冪 | - | - |
radians(dp) | dp | 把角度轉為弧度 | - | - |
random() | dp | 0~1之間的隨機數 | ||
floor(dp或numeric) | (與輸入相同) | 不大於參數的最大整數 | - | - |
round(v numeric,s int) | numeric | 圓整為s位小數 | round(42.4382,2) | 42.44 |
sign(dp或numeric) | (與輸入相同) | 參數的符號(-1,0,+1) | sing(-8,4) | -1 |
sqrt(dp或numeric) | (與輸入相同) | 平方根 | - | - |
cbrt(dp) | dp | 立方根 | - | - |
trunc(v numeric,s int) | numeric | 截斷為s位小數 | - | - |
其他常用函數
序列號生成函數——generate_series
generate_series(x,y,t)
- 1
生成多行數據從x到另外y,步長為t,默認是1
字符串列轉行——string_agg
string_agg(str,symbol [order by str])
- 1
(按照某字段排序)將str列轉行,以symbol分隔
字符串行轉列——regexp_split_to_table
…
hash函數——md5,hashbpchar
md5的hash算法精度為128位,返回一個字符串
Hashbpchar的精度是32位,返回一個integer類型
分析函數
開窗函數
聚合函數返回各個分組的結果,開窗函數則為每一行返回結果。
rank()、row_number
grouping sets
如果需要對幾個字段的組合進行group 不用,需要用到grouping sets功能
group sets語法 | 等價的普通SQL的語法 |
---|---|
SELECT C1,C2,SUM(C3)FROM T GROUP BY GROUPING SETS((C1),(C2)) | SELECT C1,NULL AS C2,SUM(C3) FROM T GROUP BY T UNION ALL SELECT NULL AS C1,C2,SUM(C3) FROM T GROUP BY YEAR |
GROUP BY GROUPING SETS((C1,C2,…Cn)) | GROUP BY C1,C2,…,Cn |
GROUP BY ROLLUP(C1,C2,…,Cn-1,Cn) | GROUP BY GROUPING SETS((C1,C2,…CCn-1,Cn),(C1,C2,…,Cn-1)…,(C1,C2),(C1),()) |
GROUP BY CUBE(C1,C2,C3) | GROUP BY GROUPING SETS((C1,C2,C3),(C1,C2),(C1,C3),(C2,C3),(C1),(C2),(C3),()) |
分區表
Greenplum支持分區表。
可以使用時間分區、Every分區、list分區、
創建分區表
[PARTITION BY partition_type (column)
[SUBPARTITION BY partition_type (column)]
[SUBPARTITION TEMPLATE (template_spec)]
[...] (partition_spec) |[SUBPARTITION BY partition_type(column)] [...] (partition_spec) [(subpartition_spec [(...)] )] ] and partition_element is: DEFAULT PARTITION name | [PARTITION name] VALUES (list_value[,...]) | [PARTITION name] START ([datatype] 'start_value') [INCLUSIVE|EXCLUSIVE] [ END ([datatype] 'end_value') [INCLUSIVE|EXCLUSIVE] [ EVERY ([datatype] [number|INTERVAL] 'interval_value')] | [PARTITION name] END ([DATATYPE] 'end_value') [INCLUSIVE|EXCLUSIVE] [ EVERY ([datatype] [number|INTERVAL] 'interval_value')] [ with (partition_storage_parameter=value [,...])] [ TABLESPACE tablespace]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
Tips
通過實驗得到:向主表插入數據時,數據會被自動存放至相應的分區表。
也可以直接向分區子表插入符合條件的數據,
當向分區子表插入不符合條件的額數據時,會提示:
[Err] ERROR: Trying to insert row into wrong partition (seg1 hadoop3:40000 pid=6679)
DETAIL: Expected partition: test_partition_range_1_prt_p20111231, provided partition: test_partition_range_1_prt_p20111230
刪除主表是會自動刪除關聯的分區表
Examples
按時間分區
create table public.test_partition_range( id numeric, name character varying(32), dw_end_date date, ) distributed by(id) PARTITION BY range(dw_end_date) ( PARTITION p20111230 START ('2011-12-30'::date) END ('2011-12-31'::date), --... );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
使用Every分區
create table test.test_partition_every( id numeric, name character varying(32), dw_end_date date ) distributed by(id) partition by range(dw_end_Date) ( partition p201112 start('2011-12-1'::date) end ('2011-12-31'::date) every ('1 days'::interval) );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
使用list分區
create table test.test_partition_list( member_id numeric, city character varying(32) )distributed by (member_id) partition by list(city) ( partition guangzhou values('guangzhou'), partition hangzhou values('hangzhou'), default partition other_city );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
修改分區表
ALTER DEFAULT PARTITION DROP DEFAULT PARTITION [IF EXISTS] DROP PARTITION [IF EXISTS] { partition_name | FOR (RANK(number)) | FOR (value) } [CASCADE] TRUNCATE DEFAULT PARTITION TRUNCATE PARTITION { partition_name | FOR (RANK(number)) | FOR (value) } RENAME DEFAULT PARTITION TO new_partition_name RENAME PARTITION { partition_name | FOR (RANK(number)) | FOR (value) } TO new_partition_name ADD DEFAULT PARTITION NAME [(subpartition_spec)] ADD PARTITION [name] partition_element [(subpartition_spec)] EXCHANGE PARTITION { partition_name | FOR (RANK(number)) | FOR (value) } WITH TABLE TABLE_NAME [WITH|WITHOUT VALIDATION] EXCHANGE EFAULT PARTITION WITH TABLE TABLE_NAME [WITH|WITHOUT VALIDATION] SET SUBPARTITION TEMPLATE (subpartition_spec) SPLIT DEFAULT PARTITION { AT (list_value) |START([datatype] range_value) [INCLUSIVE|EXCLUSIVE] END ([datatype]) range_value) [INCLUSIVE|EXCLUSIVE] } [INTO (PARTITION new_partition_name, PARTITION default_partition_name)] SPLIT DPARTITION { partition_name | FOR (RANK(number)) | FOR (value) } AT(value) [INTO (PARTITION partition_name, PARTITION partition_name]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
Examples
新增分區
alter table test.test_partition_every add partition p20120105_6 start ('2012-01-05'::date) END ('2012-01-07'::date);
- 1
- 2
drop/truncate分區
alter table test.test_partition_every drop partition p20120105_6; alter table test.test_partition_every truncate partition p20120105_6;
- 1
- 2
- 3
拆分分區
alter table test.test_partition_every split partition p20120105_6 at(('2012-01-06'::date)) into (partition p20120105,partition p20120106);
- 1
- 2
交換分區
alter table test.test_partition_every exchange partition p20120102 with table test.test_on_partition;
- 1
外部表
Greenplum在數據加載上有一個明顯的優勢,就是支持數據並發加載,gpfdist就是並發加載的工具,在數據庫中對應的就是外部表。
外部表就是一張表的數據是指向數據庫之外的數據文件的。在Greenplum中,可以對一個外部表執行正常的DML操作,當讀取數據的時候,數據庫就從數據文件中加載數據。外部表支持在Segment上並發的告訴從gpfdist導入數據,由於是直接從Segment上導入數據,所以效率非常高。
創建外部表
CREATE [READABLE] EXTERNAL TABLE TABLE_NAME
(column_name data_type [,...] | LIKE other_table) LOCATION ('file://seghost[:port]/path/file' [,...]) | ('gpfdist://filehost[:port]/file_pateern' [,...]) | ('gphdfs://hdfs_host[:port]/path/file') FORMAT 'TEXT' [( [HEADER] [DELIMITER [AS] 'delimeter' | 'OFF'] [NULL [AS] 'null string'] [ESCAPTE [AS] 'escape'|'OFF'] [NEWLINE [AS] 'LF'|'CR'|'CRLF'] [FILL MISSING FIELDS] )] | 'CSV' [( [HEADER] [QUOTE [AS] 'quote']
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
外部表需要指定gpfdist的IP和端口,詳細目錄地址。其中文件名支持通配符匹配。
可以編寫多個gpfdist的地址,但是不能超過總的Segment數,否則會報錯。在創建外部表的時候可以指定分隔符、err表、指定允許出錯的數據條數,以及源文件的字符編碼等。
外部表還支持本地文本文件的導入,效率較低,不建議使用。
外部表還支持HDFS的文件操作。
啟動gpfdist及創建外部表
1.
首先在文件服務器上啟動gpfdist服務,指定文件目錄及端口
nohup $GPHOME/bin/gpfdist -d /home/admin -p 8888 > /tmp/gpfdist.log 2>&1 &
- 1
nohup保證程序在Server端執行,當前會話關閉后,程序仍然正常運行
nohup是Unix/Linux中的一個命令,普通進程通過&符號放到后台運行,如果啟動該程序的額控制台退出,則該進程終止。nohup命令啟動程序,則在控制台退出后,進程仍然繼續運行,起到守護進程額作用。
2.
准備好需要加載的數據文件,將其放在外部表文件及其的、home/admin/目錄或該目錄的子目錄下,在Greenplum中創建對應的外部表
create external table test.test001_ext( id integer, name varchar(128) ) location ( 'gpfdist://10.20.151.11:8888/gpextdata/test001.txt' ) format 'TEXT' (delimiter as E'|' null as '' escape 'OFF') encoding 'gb18030' log errors into test.test001_err segment reject limit 10rows;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3.外部表查詢及數據加載
testDB=# select * from public.test001_ext
- 1
COPY命令
使用COPY命令可以實現將文件導出和導入,但是要通過Master,效率沒有外部表高,但是在數據量比較小的情況下,COPY命令比外部表要方面很多。
COPY table [(colum [, ...]) ] FROM {'file'|STDIN} [ [WITH] [OIDS] [HEADER] [DELIMITER [AS] 'delimeter'] [NULL [AS] 'null string'] [ESCAPE [AS] 'escape' | 'OFF'] [NEWLINE [AS] 'LF'|'CR'|'CRLF'] [CSV [QUOTE [AS] 'quote'] [FORCE NOT NULL column [,...]] [FILL MISSING FIELDS] [ [LOG ERRORS INTO error_table] [KEEP] SEGMENT REJECT LIMIT count [ROWS|PERCENT]] COPY {table [(column [,...])] |(query) } TO {'file'|STDOUT} [ [WITH] [OIDS] [HEADER] [DELIMIETER [AS] 'delimeter'] [NULL [AS] 'null string'] [ESCAPE [AS] 'escape'|'OFF'] [CSV [QUOTE [AS] 'quote'] [FORCE QUOTE column [,...]]]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
Greenplum 4.x中引入了可寫外部表,在導出數據的時候可以用可寫外部表並發導出,性能很好。但在Greeplum3.x版本中,導出數據只能通過COPY命令實現,數據在Master上匯總導出。
如果需要將數據遠程導出到其他機器上,可以使用copy to stdout,遠程執行psql連接到數據庫上,然后通過管道將數據重定向成文件。