关于GreenPlum的一些整理

本人菜鸟一只,如果有什么说错的地方还请大家批评指出!!

这篇文章用来整理下gp的一些东西,不是概念搭建七七八八的东西,就是单纯的一些sql和使用。

1、gp是分布式的数据库,跟hadoop有点类似,也是有master和slave的架构关系

摘抄作者的话:Greenplum所有的并行任务都是在Segment数据节点上完成后,Master只负责生成和优化查询计划、派发任务、协调数据节点进行并行计算,Master上的资源消耗很少有超过20%情况发生,因为Segment才是计算和加载发生的场所(当然,在HA方面,Greenplum提供Standby Master机制进行保证)。

缺陷:他和hadoop一样不支持多并发,也就是说sql不多的时候,执行速度会很快,但是如果有多个sql一起运行,就会奇慢无比!

2、索引和压缩:

索引:GreenPlum是有索引的(但是实际上,我并没有多GP的索引有多少的测试),大概如下:

-1.如果是从超大结果集合中返回非常小的结果集(不超过5%),建议使用BTREE索引(非典型数据仓库操作)

-2.表记录的存储顺序最好与索引一致,可以进一步减少IO(好的index cluster)

-3.where条件中的列用or的方式进行join,可以考虑使用索引

-4.键值大量重复时,比较适合使用bitmap索引

压缩:其实压缩也是为了加快查询速度,概念如下:

-1.不需要对表进行更新和删除操作

-2.访问表的时候基本上是全表扫描,不需要建立索引

-3.不能经常对表添加字段或者修改字段类型

实际测试:

CREATE TABLE "数据库"."表" (
"字段1" varchar(20),
"字段2" int4,
"字段3" int8,
"字段4" numeric,
....
)
WITH (APPENDONLY=true, COMPRESSLEVEL=1, ORIENTATION=column, COMPRESSTYPE=rle_type)
DISTRIBUTED randomly;

在我们的集群环境下,如下创建一张排名表,性能会比创建索引好很多(查询8s优化到1.5s),原因是因为服务器上磁盘IO经常跑满,但是cpu挺空闲的,所以把压力推到cpu让它去压缩和解压缩,缓解磁盘io的压力

3、分布键

个人觉得分布键是一个挺重要的东西,因为分布不均匀就会导致实现不了并行,从而影响查询的速度。

CREATE TABLE "数据库"."表" (
  "字段1" varchar(50),
  "字段2" varchar(500),
  "字段3" varchar(500),
    ....
  "时间" timestamp(6) DEFAULT now()
)
distributed by(字段1,字段2)
;

-1.distributed by(字段1, 字段2)

括号里面可以是一个字段,也可以是多个字段,一般来说都是通过用户id,设备mac,这种很随机的值来给定分布键。

如果在建表的时候不给定分布键,那么分布键就会是这张表的主键,或者是第一个字段。

也可以给定随机分布,把distributed by(字段1, 字段2)替换成DISTRIBUTED randomly

-2.修改分布键:alter table "数据库"."表名" set distributed randomly;

-3.查看分布情况:

select gp_segment_id,count(*) from "数据库"."表名" group by gp_segment_id;

-4.举个例子,如果你设置一个分布键叫做flag,然后这个字段只有两个值0和1,你有一个20台机器组成的GreenPlum,那这张表只会分布到两台机器上,在计算的时候,也只会动用这两台机器运算能力,其他18台在围观,所以分布键要合理分配!

4、层级关系

-1.数据库连接

-2.创建数据库

-3.创建模式(也叫schema)

-4.创建表

所以它多了一层叫做模式的东西,如下图:

 

5、关于sql

-1.窗口函数很好用!

row_number() over(partition by XXX order by XXX desc)

max() over(partition by XXX order by XXX)

avg() over(partition by XXX order by XXX)

....

-2.行列互转

--列转行(GP)
SELECT uid,String_agg(DISTINCT tag) as tag FROM (SELECT uid,tag FROM 数据库.表 
WHERE create_time BETWEEN '20180601' AND '20180701') tagtb GROUP BY uid;

--列转行(pg  postgresql)
SELECT string_agg(name,',') from test;

--行转列(pg  postgresql)
SELECT regexp_split_to_table(name,',') from test;

--行转列的去重(实际运用)
SELECT * FROM (SELECT
  regexp_split_to_table(tag_name,',') as tag 
FROM
  表A )tb 
WHERE
  tag IS NOT NULL
GROUP BY
  tag
ORDER BY
  1 ASC;
	

使用的时候注意下,不同的sql行列互转的函数传参甚至名称可能不太一样,然后如果把列转成行最好要有个分隔符,方便后面的分词查询!

-3.update(b表计算出的某一个字段设置的想要更新字段的表中,通过uid来关联)

update 数据库.想要更新字段的表 tb set 想要更新的字段=b.另一张表的相同字段 
from (SELECT uid,String_agg(DISTINCT tag) as tag 
FROM (SELECT uid,tag FROM 数据库.另一张表 WHERE 条件) tagtb 
GROUP BY uid) b 
where  tb.uid=b.uid;


--1、更新表中前10条数据(更新为固定值):

update BranchAccount
set AccountNumber = '10010'
from (select top 10 *from BranchAccountorder by ID)as t1
where BranchAccount.ID = t1.ID


--2、用一个表的字段值更新另一个表的某字段值:

update BranchAccount
set BranchAccount.AccountNumber = t1.AccountNumber
from TEMPBranchAccount as t1
where BranchAccount.ID = t1.ID


--3、更新表前10条数据(更新为另一个表的数据):

update BranchAccount
set BranchAccount.AccountNumber = t1.AccountNumber
from (select top 10 *from TEMPBranchAccount)as t1
where BranchAccount.ID = t1.ID

 

暂时写到这吧,感觉还没写完,如果以后想到什么再加进来吧,或者大家如果有什么想问的,可以给我留言!希望我能够帮上忙~

============================================================================

补充一:

记录几个关于日期的处理sql

--注:gmt_modified 这个字段是 default now()
--求当前5天的数据
select * from 库名.表明 WHERE gmt_modified >= (SELECT now() - interval '5 D')

--第二段是这样的,表A和表C中对应天的数据计算结束之后,并且确定表B中没有计算当天的数据之后,就返回要计算的日期,主要想说的是可以通过这种方式给定日期的范围to_char((SELECT now() - interval '5 D'),'yyyyMMdd') ,date_id是int类型

select *from (
select rc.date_id::VARCHAR as date_id,'${date_type}' as date_type  from ( 
select  date_id,status_flag from 表A where date_id>='${date_id}' and status_flag='Completed' ORDER BY  date_id  desc 
limit 9999 ) rc 
where  not  EXISTS (select date_id from 表B b where rc.date_id=b.date_id and rc.status_flag=b.status_flag) 
and  EXISTS (select date_id from  表C b where rc.date_id=b.date_id) 
 ) tb
where tb.date_id <=(to_char((SELECT now() - interval '5 D'),'yyyyMMdd'))
ORDER BY date_id;

--第三段是求数据库中的最新日期的前几天
select count(1),gmt_modified,next_gmt_modified from ( 
select to_char(freshtime,'yyyyMMdd') as gmt_modified,(to_char(((select max(freshtime) from 表A)  - interval '3 D'),'yyyyMMdd')) as next_gmt_modified  from 表A   
where freshtime is not null 
) tb 
where gmt_modified >=  next_gmt_modified
GROUP BY gmt_modified,next_gmt_modified ORDER BY 2 desc;

--但是第三段有个缺点,缺点是gmt_modified更新时间一般来说不会做索引什么的,如果要求这个字段的最大值,很有可能查询速度奇慢无比,因此就需要用到其他方式来解决这个问题
--例如,如果该表有自增的主键id,那么我只要拿到id最大的那条数据的更新时间,就是最新的时间,而且实际运行,第三段sql在数据多的情况下,需要查询半小时。。。但是如下sql只需要不到1秒钟!!
select * from 表A where
freshtime >= 
(
select next_gmt_modified::TIMESTAMP from ( 
select to_char(freshtime,'yyyyMMdd'),to_char((freshtime  - interval '3 D'),'yyyyMMdd') as next_gmt_modified from 表A where 主键 in (select max(主键)from  表A )
) tb ) 

补充二:

pg上的相关的元数据sql

--查询表占用空间大小
select pg_size_pretty(pg_relation_size('表名'));

--查询某张表,在某个schema上是否存在
select * from pg_class  where relname='表名'::name and relkind='r' ) a INNER JOIN 
pg_namespace b on a.relnamespace = b.oid 
WHERE nspname = 'schema名'

--杀掉某个sql
select  pg_terminate_backend(传入sqlid);

--查询当前正在执行的sql情况(可做成视图)
SELECT (( 'select  pg_cancel_backend(' :: TEXT || pg_stat_activity.procpid ) || ');' :: TEXT 
),
( now() - pg_stat_activity.query_start ) AS cost_time,
pg_stat_activity.datid,
pg_stat_activity.datname,
pg_stat_activity.procpid,
pg_stat_activity.sess_id,
pg_stat_activity.usesysid,
pg_stat_activity.usename,
pg_stat_activity.current_query,
pg_stat_activity.waiting,
pg_stat_activity.query_start,
pg_stat_activity.backend_start,
pg_stat_activity.client_addr,
pg_stat_activity.client_port,
pg_stat_activity.application_name,
pg_stat_activity.xact_start,
pg_stat_activity.waiting_reason,
pg_stat_activity.rsgid,
pg_stat_activity.rsgname,
pg_stat_activity.rsgqueueduration 
FROM
	pg_stat_activity 
WHERE
	(
	pg_stat_activity.current_query <> ALL ( ARRAY [ '<IDLE>' :: TEXT, '<insufficient privilege>' :: TEXT ] )) 
ORDER BY
	( now() - pg_stat_activity.query_start ) DESC

 

推荐的博客:https://blog.csdn.net/u010256965/article/details/50515954(关于gp的数值处理函数,作者:u010256965

老话说一下,本人菜鸟一只,如果有什么说错的地方还请大家批评指出!!我一定虚心学习!

猜你喜欢

转载自blog.csdn.net/lsr40/article/details/81118242