PostgreSQL 使用函数生成 外部表DDL

如果要生成大量的外部表, 写代码闲麻烦的话, PostgreSQL 9.5 可以通过import foreign schema 一键创建外部表, 以前的版本则可以通过如下方法快速的生成外部表的DDL.
创建postgresql外部表fdw

postgres=# create extension postgres_fdw;
CREATE EXTENSION

创建server, 指定远端数据库的ip, port, dbname

postgres=# create server fs foreign data wrapper postgres_fdw options (hostaddr '172.16.3.150', port '1921', dbname 'postgres');
CREATE SERVER

创建一个本地角色

postgres=# create role test login encrypted password 'test';
CREATE ROLE

配置本地角色teset使用server的user mapping, 指定连接到server的用户,密码.

postgres=# CREATE USER MAPPING FOR test SERVER fs OPTIONS (user 'postgres', password 'postgres');
CREATE USER MAPPING

将server的使用权给本地用户test

postgres=# grant usage on FOREIGN SERVER  fs to test;
GRANT

假设远端有一个表是orig

postgres=# \d orig
     Table "public.orig"
 Column |  Type   | Modifiers
--------+---------+-----------
 id     | integer |
 x      | numeric |

在test 用户下创建外部表

postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> create foreign table f_orig (id int, x numeric) server fs options(schema_name 'public', table_name 'orig');
CREATE FOREIGN TABLE

配置远端数据库的 pg_hba.conf, 允许访问.

postgres@db-172-16-3-150-> cd $PGDATA
postgres@db-172-16-3-150-> vi pg_hba.conf
host all all 0.0.0.0/0 md5
"pg_hba.conf" 94L, 4495C written
postgres@db-172-16-3-150-> pg_ctl reload
server signaled

测试外部表的访问

postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> select * from f_orig;
  id  |   x
------+--------
    1 |  93.23
    2 |  95.24
    3 |  95.19
.............

为了快速刷新物化视图, 原表最好有UK或PK

postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# \d orig
     Table "public.orig"
 Column |  Type   | Modifiers
--------+---------+-----------
 id     | integer |
 x      | numeric |   

postgres=# create unique index uk_orig on orig(id);
CREATE INDEX

使用如下函数自动生成外部表的DDL, 需要指定本地表的schema, tbl_name, 以及外部表需要创建在哪个schema下, 外部表的名称.

create or replace function create_ft(i_schema name, i_tbl name, i_ftschema text, i_ftname text) returns text as $$
declare
  v_attname name;
  v_type text;
  v_sql text;
  v_nt text := '';
  v_oid oid;
begin
  select oid into v_oid from pg_class where relnamespace=(select oid from pg_namespace where nspname=i_schema) and relname=i_tbl;
  v_sql := 'create foreign table '||i_ftschema||'.'||i_ftname||' (';
  for v_attname,v_type in SELECT a.attname,
    pg_catalog.format_type(a.atttypid, a.atttypmod)
    FROM pg_catalog.pg_attribute a
    WHERE a.attrelid = v_oid AND a.attnum > 0 AND NOT a.attisdropped
    ORDER BY a.attnum
  LOOP
    v_nt := v_nt||v_attname||' '||v_type||','||chr(10);
  END LOOP;
  select regexp_replace(v_nt,','||chr(10)||'$','') into v_nt;
  v_sql := v_sql||v_nt||$_$) server fs options(schema_name '$_$||i_schema||$_$', table_name '$_$||i_tbl||$_$');$_$;
  return v_sql;
end;
$$ language plpgsql strict;

如下 :

postgres=# select create_ft('pg_catalog','pg_class','public','f_orig');
                                       create_ft
----------------------------------------------------------------------------------------
 create foreign table public.f_orig (relname name,                                     +
 relnamespace oid,                                                                     +
 reltype oid,                                                                          +
 reloftype oid,                                                                        +
 relowner oid,                                                                         +
 relam oid,                                                                            +
 relfilenode oid,                                                                      +
 reltablespace oid,                                                                    +
 relpages integer,                                                                     +
 reltuples real,                                                                       +
 relallvisible integer,                                                                +
 reltoastrelid oid,                                                                    +
 relhasindex boolean,                                                                  +
 relisshared boolean,                                                                  +
 relpersistence "char",                                                                +
 relkind "char",                                                                       +
 relnatts smallint,                                                                    +
 relchecks smallint,                                                                   +
 relhasoids boolean,                                                                   +
 relhaspkey boolean,                                                                   +
 relhasrules boolean,                                                                  +
 relhastriggers boolean,                                                               +
 relhassubclass boolean,                                                               +
 relispopulated boolean,                                                               +
 relreplident "char",                                                                  +
 relfrozenxid xid,                                                                     +
 relminmxid xid,                                                                       +
 relacl aclitem[],                                                                     +
 reloptions text[]) server fs options(schema_name 'pg_catalog', table_name 'pg_class');
(1 row)

创建物化视图

postgres=# \c postgres test
You are now connected to database "postgres" as user "test".
postgres=> create materialized view mv1 as select * from f_orig;
SELECT 1053

快速刷新, 物化视图必须有UK或PK.

postgres=> create unique index uk_mv1 on mv1(id);
CREATE INDEX
postgres=> refresh materialized view concurrently mv1;
REFRESH MATERIALIZED VIEW

如果DDL不想输出换行符, 修改函数如下 :

create or replace function create_ft(i_schema name, i_tbl name, i_ftschema text, i_ftname text) returns text as $$
declare
  v_attname name;
  v_type text;
  v_sql text;
  v_nt text := '';
  v_oid oid;
begin
  select oid into v_oid from pg_class where relnamespace=(select oid from pg_namespace where nspname=i_schema) and relname=i_tbl;
  v_sql := 'create foreign table '||i_ftschema||'.'||i_ftname||' (';
  for v_attname,v_type in SELECT a.attname,
    pg_catalog.format_type(a.atttypid, a.atttypmod)
    FROM pg_catalog.pg_attribute a
    WHERE a.attrelid = v_oid AND a.attnum > 0 AND NOT a.attisdropped
    ORDER BY a.attnum
  LOOP
    v_nt := v_nt||v_attname||' '||v_type||',';
  END LOOP;
  select regexp_replace(v_nt,',$','') into v_nt;
  v_sql := v_sql||v_nt||$_$) server fs options(schema_name '$_$||i_schema||$_$', table_name '$_$||i_tbl||$_$');$_$;
  return v_sql;
end;
$$ language plpgsql strict;

批量输出DDL

postgres=# copy (select create_ft('public',tablename,'public','ft_'||tablename) from pg_tables where schemaname='public') to '/home/postgres/p';
COPY 14
postgres=> \!
[postgres@db-172-16-3-150 ~]$ cat p
create foreign table public.ft_p4 (ov integer,v_id integer,r_chkv numeric,p_yv numeric,r_xv numeric,dev numeric,v_slope numeric,v_inter numeric,v_r2 numeric,sampcnt integer) server fs options(schema_name 'public', table_name 'p4');
create foreign table public.ft_tmp1 (id integer,x numeric,y numeric) server fs options(schema_name 'public', table_name 'tmp1');
create foreign table public.ft_tmp2 (id integer,x numeric,y numeric) server fs options(schema_name 'public', table_name 'tmp2');
create foreign table public.ft_tmp3 (id integer,x numeric,y numeric) server fs options(schema_name 'public', table_name 'tmp3');
create foreign table public.ft_tmp4 (id integer,x numeric,y numeric) server fs options(schema_name 'public', table_name 'tmp4');
create foreign table public.ft_p2 (ov integer,v_id integer,r_chkv numeric,p_yv numeric,r_xv numeric,dev numeric,v_slope numeric,v_inter numeric,v_r2 numeric,sampcnt integer) server fs options(schema_name 'public', table_name 'p2');
create foreign table public.ft_zjdr (id numeric) server fs options(schema_name 'public', table_name 'zjdr');
create foreign table public.ft_zj (id integer,cnt numeric) server fs options(schema_name 'public', table_name 'zj');
create foreign table public.ft_t1 (c1 text,c2 numeric,c3 numeric,c4 numeric,c5 numeric,c6 numeric,c7 numeric) server fs options(schema_name 'public', table_name 't1');
create foreign table public.ft_test (id integer,cnt numeric) server fs options(schema_name 'public', table_name 'test');
create foreign table public.ft_orig (id integer,x numeric) server fs options(schema_name 'public', table_name 'orig');
create foreign table public.ft_tmp (id integer,x numeric,y numeric) server fs options(schema_name 'public', table_name 'tmp');
create foreign table public.ft_p3 (ov integer,v_id integer,r_chkv numeric,p_yv numeric,r_xv numeric,dev numeric,v_slope numeric,v_inter numeric,v_r2 numeric,sampcnt integer) server fs options(schema_name 'public', table_name 'p3');
create foreign table public.ft_p1 (ov integer,v_id integer,r_chkv numeric,p_yv numeric,r_xv numeric,dev numeric,v_slope numeric,v_inter numeric,v_r2 numeric,sampcnt integer) server fs options(schema_name 'public', table_name 'p1');

这样生成的代码比较紧凑, 直接执行以上生成的SQL就可以创建这些外部表了.
虽然没有import foreign schema语法简便, 但是相比手工写DDL已经好很多了.

时间: 2024-09-14 16:29:59

PostgreSQL 使用函数生成 外部表DDL的相关文章

Greenplum insert的性能(单步\批量\copy) - 暨推荐使用gpfdist、阿里云oss外部表并行导入

标签 PostgreSQL , Greenplum , HybridDB for PostgreSQL , insert , copy , 外部表 , oss , gpfdist 背景 Greenplum是一款MPP数据库产品,优势是优良的OLAP性能,支持多节点并行计算,实现PB级数据量的实时分析. 除了分析能力,数据写入吞吐也是Greenplum的重要指标,Greenplum支持从master节点写入,也支持从segment节点并行写入. 从segment并行加载的话,性能是线性提升的,因为

PostgreSQL 10 + PostGIS + Sharding(pg_pathman) + MySQL(fdw外部表) on ECS 部署指南(适合新用户)

标签 PostgreSQL , Linux , CentOS 背景 新用户部署PostgreSQL以及空间数据库插件PostGIS的指南. 内网环境RPM打包(可选项) 如果是内网环境,可以将包全部下载到本地再用rpm安装. 安装epel和postgresql yum rpm两个包后再执行: 1.使用yum-utils的yumdownloader下载需要的安装包,包括依赖包. yum install -y yum-utils yumdownloader --resolve --destdir=/

阿里云RDS PostgreSQL OSS 外部表 - 并行写提速案例

标签 PostgreSQL , oss对象存储 , 阿里云RDS PG , 并行写 , dblink , 异步调用 , 异步任务监控 , OSS外部表 , 数据传输 背景 阿里云RDS PostgreSQL.HybridDB for PostgreSQL提供了一个非常强大的功能,OSS对象存储外部表. 阿里云的RDS PostgreSQL用户可以利用OSS存储冷数据(OSS外部表的形态呈现),实现冷热分离:也可以利用OSS作为数据的中转桥梁,打通其他云端业务,例如HDB FOR PostgreS

PostgreSQL 9.5 使用 import foreign schema 语法一键创建外部表

PostgreSQL 9.5提供了一个快捷的将远程数据库中的表,视图或物化视图转换成外部表的方式, 使用import foreign schema可以直接将远端的整个schema中的所有表或部分表直接创建在本地的某个指定的schema下. Command: IMPORT FOREIGN SCHEMA Description: import table definitions from a foreign server Syntax: IMPORT FOREIGN SCHEMA remote_sc

PostgreSQL · 实现分析 · PostgreSQL 10.0 并行查询和外部表的结合

title: PostgreSQL · 实现分析 · PostgreSQL 10.0 并行查询和外部表的结合 author: 义从 前言 大家都知道,PostgreSQL 近几大版本中加入了很多 OLAP 相关特性.9.6 的并行扫描应该算最大的相关特性.在今年发布的 10.0 中,并行扫描也在不断加强,新增了并行的索引扫描. 我们知道并行扫描是支持外部数据源的.在云上,有很多存储存储产品可以以外部数据源的形式做数据库的外部存储.例如,阿里云的 OSS 和 AWS 的 S3 都是绝佳的外部数据源

如何使用外部表管理Oracle的告警日志

Oracle 告警日志时DBA维护数据库经常需要关注的一部分内容.然而告警日志以文本文件,按时间的先后顺序不断累积的形式来存储,久而 久之,势必造成告警日志的过大,难于维护和查找相关的信息.使用外表表方式来管理告警日志将大大简化维护工作量,也更直关的获取所需的 信息. 有关外部表的使用请参考:Oracle 外部表 一.告警日志的内容 消息和错误的类型(Types of messages and errors) ORA-600内部错误(ORA-600 internal errors that ne

Oracle 外部表

--================= -- Oracle 外部表 --=================       外部表只能在Oracle 9i 之后来使用.简单地说,外部表,是指不存在于数据库中的表.通过向Oracle提供描述外部表的元数据,我们 可以把一个操作系统文件当成一个只读的数据库表,就像这些数据存储在一个普通数据库表中一样来进行访问.外部表是对数据库表的延伸.   一.外部表的特性     位于文件系统之中,按一定格式分割,如文本文件或者其他类型的表可以作为外部表.     对

使用外部表管理Oracle 告警日志(ALAERT_$SID.LOG)

--================================================ -- 使用外部表管理Oracle 告警日志(ALAERT_$SID.LOG) --================================================       Oracle 告警日志时DBA维护数据库经常需要关注的一部分内容.然而告警日志以文本文件,按时间的先后顺序不断累积的形式来存储,久而 久之,势必造成告警日志的过大,难于维护和查找相关的信息.使用外表表方式来

《Hadoop实战手册》一1.10 在Greenplum外部表中使用HDFS

1.10 在Greenplum外部表中使用HDFS Greenplum是一个并行数据库,数据的存储与查询基于一个或多个PostgreSQL实例.它补充了Hadoop,提供对大数据的实时或准实时访问,它还支持使用HDFS文件作为外部表.外部表是一个处理Greenplum集群之外数据很好的解决方案.由于外部表访问首先要消耗网络带宽,所以与Greenplum集群内的数据相比,它应该存储那些访问相对不频繁的数据.本节将介绍如何创建只读的外部表和可读写的外部表. 准备工作 在本节假定你使用的Hadoop版