准备工作参见《部署》
假设基本配置如下:
- server name: cluster_zly
- proxy db role:proxy —\du
- proxy db name:proxy —\l
- data db role:zlyadmin(数据节点操作用户) —\du
- data db name:zlydb0,zlydb1(双数据节点) —\l
- schema:zly —\dn
PL/Proxy语言详解
- 共支持下列4个语句:CONNECT,CLUSTER,RUN,SELECT;
- 每个函数要么包含CONNECT,要么包含CLUSTER+RUN
- SELECT可选,如果不使用SELECT,会调用数据节点的同名函数;若使用则在数据节点直接执行此SQL;
- RUN语句也可以不使用,等价于RUN ON ANY;
CONNECT
CONNECT 'libpg connstr' | CONNECT connect_func(...) | argname;
CONNECT后面可以直接跟一个libpq的连接字符串,也可跟一个函数,由其返回一个libpq连接串;或跟一个函数参数名,指定连接哪一个数据库。
一个proxy函数中只能出现一条connect语句
CONNECT 'hostaddr=172.16.3.150 dbname=db0 user=digoal port=1921';
CLUSTER
CLUSTER 'cluster_name' | CLUSTER connect_func(...) | argname;
CLUSTER后面跟一个标识集群名称的字符串,也可以跟一个函数,由其返回一个集群名称;还可跟一个参数名,参数内容为一个集群名称。
RUN ON
RUN ON ALL | ANY | <NR> | partition_func(...);
- RUN ON ALL 表示在集群每个数据节点并行执行,必须returns setof
- RUN ON ANY 表示随机挑选一个节点执行
- RUN ON
表示指定某一数据节点的数字(0…n-1)执行 - RUN ON partition_func(…) 表示有函数particion_func()返回一个或多个hash值后将请求转到对应的后端数据节点上,如果是多个hash值,也是并行执行。
SPLIT
TARGET
TARGET other_function;
可以让后端的函数名与Proxy节点的函数名不一样,如:
<!—hexoPostRenderEscape:
CREATE OR REPLACE FUNCTION get_user_email(i_username text)
RETURNS SETOF text AS $$
CLUSTER ‘cluster_zly’;
RUN ON hashtext(i_username);
TARGET get_customer_email;
$$ LANGUAGE plproxy
proxy节点函数
ddl函数
CREATE OR REPLACE FUNCTION zly.ddlexec(query text)
RETURNS SETOF integer AS
$BODY$
CLUSTER 'cluster_zly';
RUN ON ALL;
$BODY$
LANGUAGE plproxy VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION zly.ddlexec(text)
OWNER TO postgres;
dml函数(随机insert,不适用update,delete)
CREATE OR REPLACE FUNCTION zly.dmlexec(query text)
RETURNS SETOF integer AS
$BODY$
CLUSTER 'cluster_zly';
RUN ON ANY;
$BODY$
LANGUAGE plproxy VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION zly.dmlexec(text) OWNER TO postgres;
dql函数(查询)
CREATE OR REPLACE FUNCTION zly.dqlexec(query text)
RETURNS SETOF record AS
$BODY$
CLUSTER 'cluster_zly';
RUN ON ALL;
$BODY$
LANGUAGE plproxy VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION zly.dqlexec(text) OWNER TO postgres;
data节点函数
ddl函数
CREATE OR REPLACE FUNCTION zly.ddlexec(query text)
RETURNS integer AS
$BODY$
declare
ret integer;
begin
execute query;
return 1;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
dml函数(插入)
CREATE OR REPLACE FUNCTION zly.dmlexec(query text)
RETURNS integer AS
$BODY$
declare
ret integer;
begin
execute query;
return 1;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
dql函数(查询)
CREATE OR REPLACE FUNCTION zly.dqlexec(query text)
RETURNS SETOF record AS
$BODY$
declare
ret record;
begin
for ret in execute query
loop
return next ret;
end loop;
return;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100
ROWS 1000;
测试
批量建表:
select zly.ddlexec('create table t1(id integer,name varchar(100))');
插入数据:
select zly.dmlexec('insert into t1 values(0,'aaa')');
查询数据数量:
select * from zly.dqlexec('select cast(count(id) as int) as cnt from t1 ') as (cnt int) ;
查询数据内容:
select * from zly.dqlexec('select * from t1') as (id integer, name varchar );