copyright http://cupegraf.com/
视图是指数据库只存储定义该视图的查询语句(内容是查询时产生),而物化视图是一个其查询语句查询后的内容并存储的视图(内容是创建物化视图刷新视图时产生,数据可修改。独立)。因为物化视图是视图的一个物化表结构,但是里面的数据是创建时刷新查询到额数据,当原数据更新修改时如果物化视图的表没有更新会造成数据的不一致。从9.4开始增加增量刷新,9.5的版本中支持物化视图也支持索引,修改表空间,指定用户访问权限
postgresql9.5物化视图测试:
search package: sudo apt-cache search dtrace-*
dtrac && readline install :sudo apt-get install systemtap-sdt-dev libssl-dev libpam-dev libxml2-dev libxslt-dev libtcl8.4 libperl-dev python-dev
./configure --prefix=/home/pg5/pgsql9.5-devel --with-port=5433 --with-perl --without-tcl --with-python --with-openssl --with-pam --without-ldap --with-libxml --with-libxslt --enable-thread-safety --with-blocksize=32 --enable-dtrace --enable-debug
make
sudo make install
cd postgresql源码目录/contrib
make
sudo make install(后面要用到fdw)
.bashrc的环境变量要配置:
export PGHOME=/home/pg5/pgsql9.5-devel export PATH=$PATH:$PGHOME/bin export PGDATA=/home/pg5/data export PGUSER=pg5 export PGPORT=5433
测试数据:
create database eachma ENCODING=UTF8; create table tbl(id int primary key,info text,crt_time timestamp); insert into tbl select generate_series(1,100000),md5(random()::text),clock_timestamp(); create materialized view tbl_view as select * from tbl where id<1000 with no data; create materialized view tbl_view1 as select * from tbl with no data; create unique index idx_tbl_view_id on tbl_view(id); create unique index idx_tbl_view1_id on tbl_view1(id); refresh materialized view tbl_view; refresh materialized view tbl_view1; \timing #打开事务执行时间
增量刷新;refresh materialized view concurrently tbl_view1;
非增量刷新:refresh materialized view tbl_view1;
pg中查看物化视图表:
select * from pg_matviews;
eachma=# select * from pg_matviews; -[ RECORD 1 ]+------------------------- schemaname | public matviewname | tbl_view matviewowner | pg5 tablespace | hasindexes | t ispopulated | t definition | SELECT tbl.id, + | tbl.info, + | tbl.crt_time + | FROM tbl + | WHERE (tbl.id < 1000); -[ RECORD 2 ]+------------------------- schemaname | public matviewname | tbl_view1 matviewowner | pg5 tablespace | hasindexes | t ispopulated | t definition | SELECT tbl.id, + | tbl.info, + | tbl.crt_time + | FROM tbl; Time: 0.758 ms
增量刷新不会锁表,阻断其他查询。但是视图的非增量刷新会锁表。两者利弊不一,前者不锁表,但是执行需要的时间比较长,因为是Join查询需要一条条的数据进行对比,以时间来换取查询锁。以至于不会影响到物化视图的查询工作 。而后者的执行等待时间比较短.但其他的查询需要等待刷新之后才能完成:
增量刷新:
eachma=# begin; BEGIN Time: 0.117 ms eachma=# refresh materialized view concurrently tbl_view1; REFRESH MATERIALIZED VIEW Time: 2085.527 ms eachma=# commit; COMMIT Time: 2.718 ms eachma=# end
#非增量刷新 eachma=# begin; BEGIN Time: 0.104 ms eachma=# refresh materialized view tbl_view1; REFRESH MATERIALIZED VIEW Time: 209.312 ms eachma=# commit; COMMIT Time: 9.777 ms eachma=# end; WARNING: there is no transaction in progress COMMIT Time: 0.318 ms
pg是支持外部表物化视图。例如oracle里面有一个表的数据是我们想需要的,但是一般情况下是需要我们通过odbc或者是dump出来。但是因为pg支持外部表(FDW,dblink)。可以通过创建一个我们需要oracle中数据,那么可以先创建一个外部表,然后给这个外部表创建物化视图,这样也减少的数据的拷贝,oracle有数据更新时也可以去更新视图。但要注意物化视图的表增量的刷新要与远程表规则一致(索引)
下面是做一个外部表(以postgresql9.4的库为外部库)的物化视图测试:
eachma=# CREATE EXTENSION postgres_fdw;
安装成功:
eachma=# \df List of functions Schema | Name | Result data type | Argument data types | Type --------+------------------------+------------------+---------------------+-------- public | postgres_fdw_handler | fdw_handler | | normal public | postgres_fdw_validator | void | text[], oid | normal
create server pg4 VERSION '9.4' foreign data wrapper postgres_fdw OPTIONS (host '211.69.228.50',dbname 'tech',port '5432'); #创建server CREATE USER MAPPING for pg5 server pg4 options(user 'eachma',password '612345');#创建映射用户 CREATE FOREIGN TABLE orders(order_num integer not null,order_date date not null,cust_id character(10) not null) server pg4 OPTIONS (schema_name 'public',table_name 'orders');#外部表目前不支持主健约束 eachma=# select * from pg_foreign_table; #外部表 -[ RECORD 1 ]------------------------------------- ftrelid | 16579 ftserver | 16577 ftoptions | {schema_name=public,table_name=orders}
eachma=# select * from orders; order_num | order_date | cust_id -----------+------------+------------ 20005 | 2012-05-01 | 1000000001 20006 | 2012-01-12 | 1000000003 20007 | 2012-01-30 | 1000000004 20008 | 2012-02-03 | 1000000005 20009 | 2012-02-08 | 1000000001 (5 rows) eachma=# \dt List of relations Schema | Name | Type | Owner --------+------+-------+------- public | tbl | table | pg5 (1 row)
创建一个外部表物化视图:
eachma=# create materialized view order_view as select * from orders with no data; SELECT 0 eachma=# select * from order_view; #没有刷新 ERROR: materialized view "order_view" has not been populated HINT: Use the REFRESH MATERIALIZED VIEW command. eachma=# refresh materialized view order_view; REFRESH MATERIALIZED VIEW eachma=# select * from order_view; order_num | order_date | cust_id -----------+------------+------------ 20005 | 2012-05-01 | 1000000001 20006 | 2012-01-12 | 1000000003 20007 | 2012-01-30 | 1000000004 20008 | 2012-02-03 | 1000000005 20009 | 2012-02-08 | 1000000001 (5 rows) eachma=# select * from pg_matviews; -[ RECORD 1 ]+-------------------------- schemaname | public matviewname | order_view matviewowner | pg5 tablespace | hasindexes | f ispopulated | t definition | SELECT orders.order_num,+ | orders.order_date, + | orders.cust_id + | FROM orders;
参考:http://www.postgresql.org/docs/9.5/static/postgres-fdw.html
postgresql资料:https://github.com/ty4z2008/Qix/blob/master/pg.md