MATERIALIZED VIEW

PG 9.3 版本之后开始支持物化视图。

View 视图:

虚拟,不存在实际的数据,在查询视图的时候其实是对视图内的表进行查询操作。

物化视图:

实际存在,将数据存成一张表,查询的时候对这个表进行操作。物化视图内的数据需要和表的数据进行同步,这就是refresh。

实验环境:

CentOS 7

PG 10.4

操作实验:

初始化环境:

创建表,并插入数据

mytest=# create table t1 (id int ,col1 varchar(10),col2 varchar(10));

mytest=# create table t2 (id int ,col3 varchar(10), col4 varchar(10), col5 varchar(10));

mytest=# insert into t1 values (1,'a','b'); ......

mytest=# insert into t2 values (1,'c','d','e'); ......

mytest=# select * from t1;

id | col1 | col2

----+------+------

1 | a | b

2 | a | b

3 | a | b

4 | a | b

5 | a | b

(5 rows)

mytest=# select * from t2;

id | col3 | col4 | col5

----+------+------+------

1 | c | d | e

2 | c | d | e

3 | c | d | e

4 | c | d | e

5 | c | d | e

(5 rows)

创建物化视图:

CREATE MATERIALIZED VIEW IF NOT EXISTS mv_t1_t2 (t1_id,t2_id, col1,col2,col3,col4,col5)

AS

SELECT t1.id, t2.id, t1.col1,t1.col2,t2.col3,t2.col4,t2.col5 from t1,t2

where t1.id = t2.id

WITH DATA;

mytest=# select * from mv_t1_t2;

t1_id | t2_id | col1 | col2 | col3 | col4 | col5

-------+-------+------+------+------+------+------

1 | 1 | a | b | c | d | e

2 | 2 | a | b | c | d | e

3 | 3 | a | b | c | d | e

4 | 4 | a | b | c | d | e

5 | 5 | a | b | c | d | e

(5 rows)

刷新物化视图:

mytest=# insert into t1 values (11,'x','y');

mytest=# insert into t2 values (11,'x','y','z');

对表进行操作,不改变物化视图中的数据。查询物化视图,数据没有改变

mytest=# select * from mv_t1_t2 ;

t1_id | t2_id | col1 | col2 | col3 | col4 | col5

-------+-------+------+------+------+------+------

1 | 1 | a | b | c | d | e

2 | 2 | a | b | c | d | e

3 | 3 | a | b | c | d | e

4 | 4 | a | b | c | d | e

5 | 5 | a | b | c | d | e

(5 rows)

全量更新:

刷新物化视图才能使物化视图的数据改变。

mytest=# REFRESH MATERIALIZED VIEW mv_t1_t2 WITH DATA;

mytest=# SELECT * FROM mv_t1_t2 ;

t1_id | t2_id | col1 | col2 | col3 | col4 | col5

-------+-------+------+------+------+------+------

1 | 1 | a | b | c | d | e

2 | 2 | a | b | c | d | e

3 | 3 | a | b | c | d | e

4 | 4 | a | b | c | d | e

5 | 5 | a | b | c | d | e

11 | 11 | x | y | x | y | z

(6 rows)

增量更新

只有当物化视图中存在unique index的时候,refresh物化视图才能使用增量更新,加入concurrently参数。否则报错。

mytest=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_t1_t2 WITH DATA;

ERROR: cannot refresh materialized view "public.mv_t1_t2" concurrently

HINT: Create a unique index with no WHERE clause on one or more columns of the materialized view.

mytest=# create unique index uidx_mv_id on mv_t1_t2 (t1_id );

mytest=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_t1_t2 WITH DATA;

mytest=# insert into t1 values (12,'xx','yy');

mytest=# insert into t2 values (12,'xx','yy','zz');

mytest=# REFRESH MATERIALIZED VIEW CONCURRENTLY mv_t1_t2 WITH DATA;

mytest=# select * from mv_t1_t2 ;

t1_id | t2_id | col1 | col2 | col3 | col4 | col5

-------+-------+------+------+------+------+------

1 | 1 | a | b | c | d | e

2 | 2 | a | b | c | d | e

3 | 3 | a | b | c | d | e

4 | 4 | a | b | c | d | e

5 | 5 | a | b | c | d | e

11 | 11 | x | y | x | y | z

12 | 12 | xx | yy | xx | yy | zz

(7 rows)

物化视图刷新WITH NO DATA ,查询会报错

mytest=# REFRESH MATERIALIZED VIEW mv_t1_t2 WITH NO DATA;

mytest=# select * from mv_t1_t2 ;

ERROR: materialized view "mv_t1_t2" has not been populated

HINT: Use the REFRESH MATERIALIZED VIEW command.

mytest=# REFRESH MATERIALIZED VIEW mv_t1_t2 WITH DATA;

REFRESH MATERIALIZED VIEW

mytest=# select * from mv_t1_t2 ;

t1_id | t2_id | col1 | col2 | col3 | col4 | col5

-------+-------+------+------+------+------+------

1 | 1 | a | b | c | d | e

2 | 2 | a | b | c | d | e

3 | 3 | a | b | c | d | e

4 | 4 | a | b | c | d | e

5 | 5 | a | b | c | d | e

11 | 11 | x | y | x | y | z

12 | 12 | xx | yy | xx | yy | zz

(7 rows)

---------------------

作者:Chuck_Chen1222