9.4英文文檔:http://www.postgresql.org/docs/9.4/interactive/sql-creatematerializedview.html
html
9.3中文文檔:http://www.postgres.cn/docs/9.3/sql-creatematerializedview.htmlsql
物化視圖是PG9.3新增的,物化視圖既能記住查詢SQL,也能填充數據。後期,還能在須要的時候經過refresh materialized view來實現數據刷新。(注意:目前還不支持在原表數據提交後自動刷新的功能)後端
refresh materialized view的 concurrently語法是9.4新增的,能夠在刷新視圖時不鎖住對該物化視圖的查詢工做,但在多行受影響時刷新速度會降低;該參數的原理和優缺點與索引的concurrently相似,以時間來換取查詢鎖,刷新的速度會變慢。安全
CREATE MATERIALIZED VIEW table_name [ (column_name [, ...] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ TABLESPACE tablespace_name ] AS query [ WITH [ NO ] DATA ]
是一個PostgreSQL擴展。 函數
CREATE MATERIALIZED VIEW用來定義一個查詢的物化視圖。在命令發出時,查詢會被執行而且默認用來填充該物化視圖(使用WITH NO DATA則不會填充)。以後能夠經過REFRESH MATERIALIZED VIEW來刷新。post
物化視圖和表有不少相同的屬性,可是物化視圖不支持臨時物化視圖和自動生更OID(既不支持WITH oid語法)。 ui
CREATE MATERIALIZED VIEW: 既保存數據,又保存SQL;
spa
CREATE TABLE AS:只保存數據,不保存sql;.net
CREATE VIEW:不保存數據,只保存SQL;postgresql
table_name:是要建立的物化視圖的名稱(能夠有模式修飾)。
column_name:物化視圖的列名。若是不提供column_name,將從查詢結果中去獲取。
storage_parameter:該自居爲物化視圖指定可選的存儲參數。請參照 Storage Parameters 。全部 CREATE TABLE 支持的參數CREATE MATERIALIZED VIEW也都支持,除了OID。請參照 CREATE TABLE。
tablespace_name:指定本物化視圖會被建立到哪一個表空間。若是不指定,則會使用default_tablespace。
query:是一個SELECT, TABLE,或者 VALUES 查詢.該查詢將在一個受限制的安全操做中執行。對自身建立臨時表的函數的調用會失敗。
VALUES(1,'lily'); 等價於 select 1, 'lily'; values(1,'lily'),(2,'lucy'); 等價於 select 1 AS column1,'lily' AS column2 union select 2,'lucy'; TABLE name;等價於 SELECT * FROM name
WITH [NO] DATA: 聲明物化視圖是否在建立時填充數據。若是不填充的話,該物化視圖將會被標記爲不可掃描的,直到首次REFRESH MATERIALIZED VIEW執行後才能被查詢。
table=# create table lyy(id int primary key, name varchar); CREATE TABLE table=# insert into lyy select generate_series(1,10),'name'; INSERT 0 10 table=# select * from lyy; id | name ----+------ 1 | name 2 | name ..... (10 rows) --建立物化視圖with data或者缺省時,物化視圖會被填充,處於可掃描狀態 table=# create materialized view lyy_mv (id, name) as select id,name from lyy; SELECT 10 table=# select * from lyy_mv; id | name ----+------ 1 | name 2 | name ..... (10 rows)
REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] name [ WITH [ NO ] DATA ]
REFRESH MATERIALIZED VIEW 會徹底替代物化視圖的原有內容,原有內容會被捨棄。若是聲明瞭WITH DATA(或者是缺省),會執行後端查詢來提供新的數據,物化視圖的將保留在可掃描狀態。若是聲明瞭WITH NO DATA,物化視圖將保留在不可掃描的狀態。
CONCURRENTLY和WITH NO DATA不能同時使用,不然會報錯。
name:要刷新的物化視圖的名字(能夠有模式修飾)。
CONCURRENTLY:刷新物化視圖而不鎖定物化視圖上的查詢。不指定concurrently選項時,一次影響不少行的刷新,將會使用更少的資源而且完成地更迅速,可是會鎖定其餘試圖從該物化視圖讀數據的連接。該選項在少許行受影響時,可能速度會更快。
該選項僅在這種狀況下才能使用:在物化視圖上有至少一個UNIQUE索引,Unique索引僅使用列名並涵蓋全部行。也就是說,必須首先建立至少一個,在物化視圖的一個或多個字段上,沒有where子句的,UNIQUE索引,才能使用concurrently選項;不然會報錯。
在物化視圖未被填充時,不能使用該選項;不然會報錯。
即便一次運行一個帶有該選項的REFRESH,也可能會與任何一個物化視圖造成競態。
--原表數據增長後,不刷新物化視圖,物化視圖的數據就不會變 table=# insert into lyy values(11,'lyy'); INSERT 0 1 table=# select * from lyy_mv; id | name ----+------ 1 | name 2 | name ...... (10 rows) --使用with data或者缺省刷新物化視圖後,新數據會填充,原數據被捨棄 table=# refresh materialized view lyy_mv with data; REFRESH MATERIALIZED VIEW table=# select * from lyy_mv; id | name ----+------ 1 | name 2 | name ...... 11 |lyy (11 rows) --使用with no data刷新物化視圖,原數據被捨棄,未填充新數據,將處於不可掃描狀態。 table=# refresh materialized view lyy_mv with no data; REFRESH MATERIALIZED VIEW table=# select * from lyy_mv; ERROR: materialized view "lyy_mv" has not been populated detail: Use the REFRESH MATERIALIZED VIEW command. --重現刷新物化視圖後,原數據恢復,物化視圖又能夠進行掃描 table=# refresh materialized view lyy_mv; REFRESH MATERIALIZED VIEW table=# select * from lyy_mv; id | name ----+------ 1 | name 2 | name ...... 11 |lyy (11 rows) --必須先建立至少一個unique索引(無where子句,至少涉及一個字段),才能使用concurrently table=# refresh materialized view concurrently lyy_mv with data; ERROR: cannot refresh materialized view "public.lyy_mv" concurrently detail: Create a unique index with no WHERE clause on one or more columns of th e materialized view. table=# create unique index lyy_mv_uindex on lyy_mv (id); CREATE INDEX table=# refresh materialized view concurrently lyy_mv with data; REFRESH MATERIALIZED VIEW --concurrently與with no data 不能同時使用. table=# refresh materialized view concurrently lyy_mv with no data; ERROR: CONCURRENTLY and WITH NO DATA options cannot be used together --物化視圖未被填充時,不能使用concurrently. table=# refresh materialized view lyy_mv with no data; REFRESH MATERIALIZED VIEW table=# refresh materialized view concurrently lyy_mv with no data; ERROR: CONCURRENTLY cannot be used when the materialized view is not populated
多事務中,物化視圖的普通更新會阻塞對它的查詢,currently更新不會阻塞查詢。
物化視圖的普通更新:
--事務1 table=# begin; BEGIN table=# select pg_backend_pid(); pg_backend_pid ---------------- 3644 table=# refresh materialized view lyy_mv with data; REFRESH MATERIALIZED VIEW --事務2 table=# begin; BEGIN table=# select pg_backend_pid(); pg_backend_pid ---------------- 1316 table=# select pid,mode,relation,granted from pg_locks where relation='lyy_mv'::regclass; pid | mode | relation | granted ------+---------------------+----------+--------- 3644 | AccessShareLock | 74440 | t 3644 | ShareLock | 74440 | t 3644 | ExclusiveLock | 74440 | t 3644 | AccessExclusiveLock | 74440 | t (4 rows) --事務3 table=# begin; BEGIN table=# select pg_backend_pid(); pg_backend_pid ---------------- 2772 table=# select * from lyy_mv; --查詢處於等待狀態 --事務2 table=# select pid,mode,relation,granted from pg_locks where relation='lyy_mv'::regclass; pid | mode | relation | granted ------+---------------------+----------+--------- 2772 | AccessShareLock | 74440 | f 3644 | AccessShareLock | 74440 | t 3644 | ShareLock | 74440 | t 3644 | ExclusiveLock | 74440 | t 3644 | AccessExclusiveLock | 74440 | t (5 rows)
物化視圖的concurrently更新:
--事務1 table=# begin; BEGIN table=# select pg_backend_pid(); pg_backend_pid ---------------- 3644 table=# refresh materialized view concurrently lyy_mv with data; REFRESH MATERIALIZED VIEW --事務2 table=# begin; BEGIN table=# select pid,mode,relation,granted from pg_locks where relation='lyy_mv': :regclass; pid | mode | relation | granted ------+------------------+----------+--------- 3644 | AccessShareLock | 74440 | t 3644 | RowExclusiveLock | 74440 | t 3644 | ExclusiveLock | 74440 | t (3 rows) --事務3 table=# begin; BEGIN table=# select pg_backend_pid(); pg_backend_pid ---------------- 2772 table=# select * from lyy_mv; id | name ----+------ 1 | name 2 | name ...... 11 | lyy (11 rows) --查詢能夠執行,未被阻塞 --事務2 table=# select pid,mode,relation,granted from pg_locks where relation='lyy_mv'::regclass; pid | mode | relation | granted ------+------------------+----------+--------- 2772 | AccessShareLock | 74440 | t 3644 | AccessShareLock | 74440 | t 3644 | RowExclusiveLock | 74440 | t 3644 | ExclusiveLock | 74440 | t (4 rows)
物化視圖的普通更新要比concurrently更新的效率高不少。
table=# create table yy(id int primary key,name varchar); CREATE TABLE table=# create materialized view yy_mv(id,name) as select id, name fro no data; SELECT 0 table=# insert into yy(id,name) select generate_series(1,100000),'name INSERT 0 100000 table=# select count(*) from yy; count -------- 100000 table=# \timing Time is on. --普通刷新 table=# refresh materialized view yy_mv with data; REFRESH MATERIALIZED VIEW Time: 54.606 ms table=# select count(*) from yy_mv; count -------- 100000 --concurrently刷新,明顯慢了不少.(此處不考慮數據量很小的狀況) --首先得爲物化視圖建立無where子句的unique索引。 table=# create unique index yy_mv_uindex on yy_mv(id); CREATE INDEX table=# refresh materialized view concurrently yy_mv with data; REFRESH MATERIALIZED VIEW TIME: 226.042 ms table=# select count(*) from yy; count -------- 100000
DROP MATERIALIZED VIEW [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
DROP MATERIALIZED VIEW 刪除已存在的物化視圖。要執行該命令必須是該物化視圖的全部者。
IF EXISTS : 若是物化視圖不存在不會拋出錯誤,僅發送一個提示信息。
name: 要移除的物化視圖的名稱(能夠有模式修飾)。
CASCADE:自動刪除依賴該物化視圖的對象(好比其餘的物化視圖或者普通視圖)。
RESTRICT : 若是有任何對象依賴於該物化視圖,則拒絕刪除該物化視圖。(這是缺省的)。
參考資料:
http://francs3.blog.163.com/blog/static/405767272014421104127225/