要获取文件空间的信息,可以查看系统日志表pg_filespace和pg_filespace_entry。
可通过与pg_tablespace关联查看表空间的完整定义:
SELECT spcname as tblspc, fsname as filespc, fsedbid as seg_dbid, fselocation as datadir
FROM pg_tablespace pgts, pg_filespace pgfs, pg_filespace_entry pgfse
WHERE pgts.spcfsoid=pgfse.fsefsoid AND pgfse.fsefsoid=pgfs.oid ORDER BY tblspc, seg_dbid;
模式搜索路径
要知道在DB的哪个模式下搜索需要的对象,可以通过明确指定模式名的方式来实现。
SELECT * FROM zhangyun_schema.mybigtable;
若不想通过指定模式名称的方式来实现,可以通过设置search_path参数来完成。
1) 设置模式搜索路径
该参数可以通过ALTER DATABAST命令修改DB的模式搜索路径
ALTER DATABASE zhangyun_db SET search_path TO zhangyun_schema, public, pg_catalog;
还可以通过ALTER ROLE命令修改特定ROLE(User)的模式搜索路径。例如:
ALTER ROLE zhangyun SET search_path TO zhangyun_schema, public, pg_catalog;
2) 查看当前的模式
SELECT current_schema();
SHOW search_path;
** 创建只追加表
CREATE TABLE test (id int, name text) WITH (appendonly=true);
演示delete和update对ao表的操作:
zhangyun_db=# insert into test values(1,‘hello‘);
INSERT 0 1
zhangyun_db=# insert into test values(2,‘spark‘);
INSERT 0 1
zhangyun_db=# update test set name = ‘scala‘ where id = 1;
UPDATE 1
zhangyun_db=# select * from test;
id | name
----+-------
1 | scala
2 | spark
(2 rows)
zhangyun_db=# delete from test where id = 1;
DELETE 1
zhangyun_db=# select * from test;
id | name
----+-------
2 | spark
(1 row)
######选择行存储或者列存储(Row or Column Orientation)######
考虑行存的情况:
(1) 表数据的更新
如果一张表在装载完之后一定有更新操作,那么就选择行存表。
template1=# ALTER TABLE foo SET WITH (REORGANIZE=TRUE); #重分布数据
template1=# select get_ao_distribution(‘foo‘);
get_ao_distribution
---------------------
(3,2500004)
(0,2500003)
(1,2500004)
(2,2500003)
(4 rows)
template1=# ALTER TABLE foo SET DISTRIBUTED BY (a); #重新设置分布策略
ALTER TABLE
template1=# select get_ao_distribution(‘foo‘);
get_ao_distribution
---------------------
(1,2500033)
(2,2499974)
(3,2500037)
(0,2499970)
(4 rows)
重分布表数据
对于随机分布策略或者不改变分布策略的表,要重分布TABLE的数据,使用REORGANIZW=TRUE。
这在处理数据倾斜问题时可能是很必要的,在添加新的Segment节点资源时也是必要的。
ALTER TABLE sales SET WITH (REORGANIZE=TRUE);
该命令会在Instance之间按照现有的分布策略(包括随机分布策略)重新平衡表中数据。
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;
8) 在现有表上添加压缩列
可以使用ALTER TABLE命令来添加一个压缩列。
ALTER TABLE T1 ADD COLUMN c4 int DEFAULT 0 ENCODING (COMPRESSTYPE=zlib);
9) 继承压缩设置
创建一个带子分区设置的表,然后增加一个分区:
CREATE TABLE ccddl (i int, j int, k int, l int)
WITH (APPENDONLY = TRUE, ORIENTATION=COLUMN)
PARTITION BY range(j)
SUBPARTITION BY list (k)
SUBPARTITION template(
SUBPARTITION sp1 values(1, 2, 3, 4, 5),
COLUMN i ENCODING(COMPRESSTYPE=ZLIB),
COLUMN j ENCODING(COMPRESSTYPE=lz4), #Vitesse DeepGreen does not support quicklz. Please use lz4 or set vitesse.lz4_replace_quicklz.
COLUMN k ENCODING(COMPRESSTYPE=ZLIB),
COLUMN l ENCODING(COMPRESSTYPE=ZLIB))
( PARTITION p1 START(1) END(10),
PARTITION p2 START(10) END(20)
);
ALTER TABLE ccddl ADD PARTITION p3 START(20) END(30);
定义日期范围分区表
日期范围分区表使用单个date或者timestamp字段作为分区键。
可以通过使用START值、 END值和EVERY子句定义分区增量让GPDB自动产生分区。
缺省情况下, START值总是被包含而END值总是被排除。
CREATE TABLE sales (id int, date date, amt decimal(10,2))
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
( START (date ‘2008-01-01‘) INCLUSIVE
END (date ‘2009-01-01‘) EXCLUSIVE
EVERY (INTERVAL ‘1 day‘) );
定义数字范围分区表
数字范围分区表使用单个数字列作为分区键。例如:
CREATE TABLE rank (id int, rank int, year int, gender char(1), count int)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( START (2001) END (2008) EVERY (1),
DEFAULT PARTITION extra
);
CREATE TABLE rank (id int, rank int, year int, gender char(1), count int )
DISTRIBUTED BY (id)
PARTITION BY LIST (gender)
( PARTITION girls VALUES (‘F‘),
PARTITION boys VALUES (‘M‘),
DEFAULT PARTITION other );
定义多级分区表
使用subpartition template来确保每个分区具有相同的子分区结构,尤其是对那些后增加的分区来说。
CREATE TABLE sales (trans_id int, date date, amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION usa VALUES (‘usa‘),
SUBPARTITION asia VALUES (‘asia‘),
SUBPARTITION europe VALUES (‘europe‘),
DEFAULT SUBPARTITION other_regions
)
( START (date ‘2008-01-01‘) INCLUSIVE END (date ‘2009-01-01‘) EXCLUSIVE
EVERY (INTERVAL ‘1 month‘),
DEFAULT PARTITION outlying_dates
);
下面是一个3级分区表的例子,这里表sales被分区为年、月、区域。 SUBPARTITION TEMPLATE子句确保每个年分区有相同的子分区结构。
另外,每个级别的分区都有一个默认分区:
CREATE TABLE sales (id int, year int, month int, day int, region text) DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
SUBPARTITION BY RANGE (month)
SUBPARTITION TEMPLATE
(
START (1) END (13) EVERY (1),
DEFAULT SUBPARTITION other_months
)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION usa VALUES (‘usa‘),
SUBPARTITION europe VALUES (‘europe‘),
SUBPARTITION asia VALUES (‘asia‘),
DEFAULT SUBPARTITION other_regions
)
( START (2002) END (2010) EVERY (1),
DEFAULT PARTITION outlying_years
);
将现有表分区
对已经创建的表是不能分区的。只能在CREATE TABLE的时候做分区。要想对现有的表做分区,只能重新创建一个分区表、重新装载数据到新的分区表中、删
掉旧表然后把新的分区表改为旧表的名称。还必须重新对TABLE做授权。
CREATE TABLE sales2 (LIKE sales)
PARTITION BY RANGE (date)
( START (date ‘2008-01-01‘) INCLUSIVE END (date ‘2009-01-01‘) EXCLUSIVE
EVERY (INTERVAL ‘1 month‘)
);
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;
由于分区不要求有名称,若分区没有名称,下面的表达式仍可以指定一个分区:
PARTITION FOR (value) or PARTITION FOR(RANK(number))
(1) 添加新分区
如果原有的分区表包含了subpartition template设计,新增的分区将根据该模版创建子分区。
CREATE TABLE sales (trans_id int, date date, amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
(
SUBPARTITION usa VALUES (‘usa‘),
SUBPARTITION asia VALUES (‘asia‘),
SUBPARTITION europe VALUES (‘europe‘),
DEFAULT SUBPARTITION other_regions
)
( START (date ‘2008-01-01‘) INCLUSIVE END (date ‘2009-01-01‘) EXCLUSIVE
EVERY (INTERVAL ‘1 month‘),
DEFAULT PARTITION outlying_dates
);
ALTER TABLE sales ADD PARTITION
START (date ‘2009-02-01‘) INCLUSIVE
END (date ‘2009-03-01‘) EXCLUSIVE;
如果在创建TABLE时没有subpartition template,在新增分区时需要定义子分区:
ALTER TABLE sales ADD PARTITION
START (date ‘2009-02-01‘) INCLUSIVE
END (date ‘2009-03-01‘) EXCLUSIVE
( SUBPARTITION usa VALUES (‘usa‘),
SUBPARTITION asia VALUES (‘asia‘),
SUBPARTITION europe VALUES (‘europe‘) );
添加缺省分区
ALTER TABLE sales ADD DEFAULT PARTITION other;
如果是多级分区表, 同一层次中的每个分区都需要一个默认分区。
ALTER TABLE sales ALTER PARTITION FOR (RANK(1)) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR (RANK(2)) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR (RANK(3)) ADD DEFAULT PARTITION other;
RANK(partitionrank)指的是范围分区同一层级中的顺序。partitionrank可参见pg_partition表。
(2)删除分区
ALTER TABLE sales DROP PARTITION FOR (RANK(1));
(3)清空分区数据
在清空一个包含子分区的分区时,其所有相关子分区的数据都自动被清空。
ALTER TABLE sales TRUNCATE PARTITION FOR (RANK(1));
(4)交换分区:
CREATE TABLE jan08 (LIKE sales) WITH (appendonly=true);
INSERT INTO jan08 SELECT * FROM sales_1_prt_1 ;
ALTER TABLE sales EXCHANGE PARTITION FOR (DATE ‘2008-01-01‘) WITH TABLE jan08
(5)拆分分区
拆分分区是将现有的一个分区分成两个分区。 使用ALTER TABLE命令来拆分分区。只能拆分最低层级的分区表(只有包含数据的分区可以拆分)。
指定的分割值对应的数据将进入后面一个分区(就是STAER为INCLUSIVE)。
ALTER TABLE sales SPLIT PARTITION FOR (‘2008-01-01‘)
AT (‘2008-01-16‘) INTO (PARTITION jan081to15, PARTITION jan0816to31);
如果分区表有默认分区,要添加新的分区只能从默认分区拆分。而且只能从最低层级分区的默认分区拆分(只有包含数据的分区可以拆分)。
在使用INTO子句时,第2个分区名称必须是已经存在的默认分区。
ALTER TABLE sales SPLIT DEFAULT PARTITION
START (‘2009-01-01‘) INCLUSIVE
END (‘2009-02-01‘) EXCLUSIVE
INTO (PARTITION jan09, default partition);
(6)修改子分区模版
使用ALTER TABLE SET SUBPARTITION TEMPLATE命令来修改现有分区表的子分区模版。 在修改了子分区模版之后添加的分区,
其子分区将按照新的模版产生。已经存在的分区不会被修改。
ALTER TABLE sales SET SUBPARTITION TEMPLATE
( SUBPARTITION usa VALUES (‘usa‘),
SUBPARTITION asia VALUES (‘asia‘),
SUBPARTITION europe VALUES (‘europe‘),
SUBPARTITION africa VALUES (‘africa‘)
DEFAULT SUBPARTITION other
);
ALTER TABLE sales ADD PARTITION sales_prt_3
START (‘2009-03-01‘) INCLUSIVE END (‘2009-04-01‘) EXCLUSIVE;
这个例子在一级分区有默认分区时是不能执行的,要查看效果,先删除默认分区。
要删除子分区模版,使用SET SUBPart TEMPLATE并使用空的参数来完成。
ALTER TABLE sales SET SUBPARTITION TEMPLATE ();
11) 创建与使用序列
(1)创建序列
CREATE SEQUENCE myserial START 101;
(2)使用序列
获取序列的下一个值并插入表中:
INSERT INTO vendors VALUES (nextval(‘myserial‘), ‘acme‘);