文章目录

  • 1.视图
  • 2.物化视图
  • 3.视图和物化视图的对比
  • 4.示例:查询系统的用户表
    • 4.1 视图
      • 4.1.1 创建视图
      • 4.1.2 使用视图
      • 4.1.3 查看视图的执行计划
      • 4.1.4 视图的时效性
      • 4.1.5 尝试为视图创建索引
      • 4.1.6 删除视图
    • 4.2 物化视图
      • 4.2.1 创建物化视图
      • 4.2.2 使用物化视图
      • 4.2.3 查看物化视图的执行计划
      • 4.2.4 视图的时效性
      • 4.2.5 尝试为物化视图创建索引
      • 4.2.6 删除物化视图
    • 4.3.物化视图延伸
      • 4.3.1并发刷新物化视图
      • 4.3.2尝试修改物化视图的数据

我们常用说的视图一般是指 view,即普通视图;而物化视图则是materialized view(materialized 使物质化,使具体化(materialize 的过去式和过去分词))。两者都是视图,但是名称不一样,说明两者还有有所差异的。下面就来简单介绍一下PostgreSQL中的视图和物化视图的差异。

1.视图

对标实体表,视图其实是个虚拟的表,实际上一个SQL拼接而成的虚拟表(假表),可能是有一个表或者多个表、视图关联而成的复杂的SQL,而这个SQL一般都是select语句(当然也可能是 update、delete 等的语句,但是可能会有诸多限制,而且用视图进行这些操作也不安全,一般也不会这么用,这些不在本文讨论范围内。)。而视图的用途常常用于展示一些用户需要的信息,隐藏一些敏感或者是不重要的数据,汇总一些关键数据展示给用户。

操作:可以像表一样查询视图的字段,也可以当做一个表进行关联查询。
查询底层实现:通过创建视图的语句进行查询,就是每次实时查询底层的表,数据都是实时的。
索引:走表的索引。

2.物化视图

基本功能和视图类型。对标实体表和普通视图,会比普通视图更像一个表。上面说到视图是一个虚拟的表,这个物化视图其实是一个物理表,它可以用自己的索引。

操作:可以像表一样查询视图的字段,也可以当做一个表进行关联查询。可以创建索引。
查询底层实现:创建后就真的被当做是表了,即结果都物化(固化)成了一个表,假如创建语句的底层表数据有变化,也不会影响到这个物化视图的数据,除非手动进行刷新。就是每次查询的都是固化的数据,不是实时的数据。
索引:走自己的索引,可以创建索引。

3.视图和物化视图的对比

类型\对比项 物理结构 时效性 有无索引
视图 虚拟表 实时 无索引
物化视图 物理表 非实时 可以创建索引

4.示例:查询系统的用户表

基础查询如下,后面我们会使用这个SQL来构造视图和物化视图。
(简单介绍下pg_class :pgsql里面的一个内置系统表,是一个统计或者说是汇总的数据表。class就是类、对象,即pgsql里面的对象都会在这里面记录,比如实体表、视图、物化视图、索引、toast表等,详细信息可以查看官方文档。)

select * from pg_class where relnamespace != '11' and relnamespace != '13887'  and relkind = 'r';-- 创建一个表,备用
create table Sheet4(id int8,name varchar(100)
);-- 查询该表的基础信息(元数据信息)
select * from pg_class where relnamespace != '11' and relnamespace != '13887'  and relkind = 'r' and  relname = 'Sheet4';

4.1 视图

4.1.1 创建视图

CREATE VIEW "public"."v_user_tab"
AS
select * from pg_class where relnamespace != '11' and relnamespace != '13887'  and relkind = 'r';

4.1.2 使用视图

-- 普通查询
select * from v_user_tab;
select * from v_user_tab where relname = 'Sheet4';

-- 关联查询,找命名空间是啥(public默认的)
select * from pg_namespace;
select ns.nspname,vt.* from v_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid;
select ns.nspname,vt.* from v_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid where relname = 'Sheet4';

4.1.3 查看视图的执行计划

查看索引使用情况:上面提到了,实际上走的是底层的查询,索引走的也是原来基础表上的索引。下面我们来看下是不是。(注意一下,因为pgsql规则器有自己的考量,有时候即使有索引也不一定会走,和具体的表记录和查询语句有关系。因此可能explain结果和本文可能会有点不一致。)

通过计划可以看到这个表名的简单SQL,使用了系统表 pg_class 上的索引 pg_class_relname_nsp_index 。

explain select * from v_user_tab where relname = 'Sheet4';Index Scan using pg_class_relname_nsp_index on pg_class  (cost=0.28..8.31 rows=1 width=271)Index Cond: (relname = 'Sheet4'::name)Filter: ((relnamespace <> '11'::oid) AND (relnamespace <> '13887'::oid) AND (relkind = 'r'::"char"))

下面这个使用了,两个索引:pg_class.pg_class_relname_nsp_index 和pg_namespace.pg_namespace_oid_index 。

explain select ns.nspname,vt.* from v_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid where relname = 'Sheet4';Merge Left Join  (cost=0.43..12.02 rows=1 width=335)Merge Cond: (pg_class.relnamespace = ns.oid)->  Index Scan using pg_class_relname_nsp_index on pg_class  (cost=0.28..8.31 rows=1 width=271)Index Cond: (relname = 'Sheet4'::name)Filter: ((relnamespace <> '11'::oid) AND (relnamespace <> '13887'::oid) AND (relkind = 'r'::"char"))->  Index Scan using pg_namespace_oid_index on pg_namespace ns  (cost=0.14..18.81 rows=244 width=68)

4.1.4 视图的时效性

创建一个表,看能不能在这个视图里面查到。

create table testv1(id int8,name varchar(100)
);
-- 有数据,说明数据是实时的。
select * from v_user_tab where relname = 'testv1';

4.1.5 尝试为视图创建索引

create index idx_v_user_tab_relname on v_user_tab using btree (relname);
-- 会报错:> 错误:  "v_user_tab" 不是一个表或物化视图

4.1.6 删除视图

drop view v_user_tab;

4.2 物化视图

4.2.1 创建物化视图

CREATE MATERIALIZED VIEW "public"."mv_user_tab"
AS
select * from pg_class where relnamespace != '11' and relnamespace != '13887'  and relkind = 'r';

4.2.2 使用物化视图

-- 普通查询
select * from mv_user_tab;
select * from mv_user_tab where relname = 'Sheet4';

-- 关联查询
select * from pg_namespace;
select ns.nspname,vt.* from mv_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid;
select ns.nspname,vt.* from mv_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid where relname = 'Sheet4';


基础使用,到目前为止好像都没有差异。

4.2.3 查看物化视图的执行计划

explain select * from mv_user_tab where relname = 'Sheet4';Seq Scan on mv_user_tab  (cost=0.00..55.53 rows=1 width=260)Filter: (relname = 'Sheet4'::name)

没有走索引,根据上面的查询我们可以知道其实 pg_class.relname 是有索引的,但是这里没有用到。
其实不是这样的,这里和视图就有点不一样,当它创建后,我们应该把物化视图当做一个独立的个体(独立的表),它有索引,它只走自己的索引(等下我们尝试为这个字段创建索引)。

explain select ns.nspname,vt.* from mv_user_tab vt left join  pg_namespace ns on vt.relnamespace = ns.oid where relname = 'Sheet4';Merge Right Join  (cost=55.76..55.86 rows=1 width=324)Merge Cond: (ns.oid = vt.relnamespace)->  Index Scan using pg_namespace_oid_index on pg_namespace ns  (cost=0.14..18.81 rows=244 width=68)->  Sort  (cost=55.54..55.54 rows=1 width=260)Sort Key: vt.relnamespace->  Seq Scan on mv_user_tab vt  (cost=0.00..55.53 rows=1 width=260)Filter: (relname = 'Sheet4'::name)

这个也没有走索引,使用的是全表扫描。

4.2.4 视图的时效性

创建一个表,看能不能在这个物化视图里面查到。

create table testv2(id int8,name varchar(100)
);
-- 没有数据,说明数据不是实时的。
select * from mv_user_tab where relname = 'testv2';

我们刷新一下物化视图

refresh materialized view  mv_user_tab;
-- 刷新后,我们就可以查到刚才那个表了
select * from mv_user_tab where relname = 'testv2';

4.2.5 尝试为物化视图创建索引

create index idx_mv_user_tab_relname on mv_user_tab using btree (relname);

这里我们再执行这个语句,发现是可以走索引的。

explain select * from mv_user_tab where relname = 'Sheet4';Index Scan using idx_mv_user_tab_relname on mv_user_tab  (cost=0.28..8.29 rows=1 width=260)Index Cond: (relname = 'Sheet4'::name)--删除索引
DROP index idx_mv_user_tab_relname;

4.2.6 删除物化视图

drop materialized view mv_user_tab;

注意删除物化视图会同步删除对应的索引(和删除表会删除表对应的索引是一样的道理),但是刷新物化视图不会。

4.3.物化视图延伸

4.3.1并发刷新物化视图

refresh (全量刷新)默认会为视图加上排它锁,会阻塞查询。

生产上,我们为了安全,我们一般采用“并发的方式”刷新物化视图。并发刷新的意思就是我刷新的时候,你还可以查询对应的数据。(注意:如果逻辑表复制、数据比较多,并发刷新可能需要时间比较长,而且只能同时刷新一个物化视图,但是整理来说不影响。)

-- 比如这样
refresh materialized view concurrently mv_user_tab;
> 错误:  不能同时刷新物化视图 "public.mv_user_tab"
> HINT:  在物化视图的一个或多个列上创建不带WHERE子句的唯一索引.

(因为还没研究过对应文档)个人理解,并发刷新就是根据唯一索引判断是新增还是更新数据到物化视图里面,因此需要先有唯一索引。

-- 创建唯一索引
create unique index idx_mv_user_tab_oid on mv_user_tab using btree (oid);
-- 再次尝试并发刷新
refresh materialized view concurrently mv_user_tab;

4.3.2尝试修改物化视图的数据

尝试删除数据

select * from mv_user_tab where relname = 'testv2';DELETE from mv_user_tab where relname = 'testv2';> 错误:  不能改变物化视图 "mv_user_tab"

尝试更新物化视图

update  mv_user_tab set relname = 'testv21' where relname = 'testv2';> 错误:  不能改变物化视图 "mv_user_tab"

经过尝试:发现除了刷新操作外,物化视图的数据是不能进行修改和删除操作的。

PostgreSQL视图和物化视图相关推荐

  1. 数据库视图解析[普通视图、物化视图以及通过修改视图修改数据]

    1. 关系型数据库的视图 1.1. 视图 视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式 ...

  2. 普通视图和物化视图的区别(转)

    物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的. 普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL ...

  3. Oracle物化视图与物化视图日志

    文章目录 物化视图 物化视图与普通视图的区别 创建一个存放person的表 创建一个存放person的address的表 初始化数据 创建物化视图的语句 1.build [immediate|defe ...

  4. Hive视图与物化视图

    文章目录 1. 视图 1.2 案例 1.3 视图的好处 2. Hive3.0新特性:Materialized View 物化视图 2.1 物化视图语法 2.2 基于物化视图的查询重写 1. 视图 Hi ...

  5. 普通视图和物化视图的区别

    物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的. 普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL ...

  6. 浅谈SQL Server索引视图(物化视图)以及索引视图与查询重写

    目录 (一)前言 (二)正文 1. 物化视图(索引视图)与查询重写的基本概念 2. 创建测试环境 (1)建表 (2)写数据 3. 索引视图创建 (1)创建语法 (2)为索引视图创建索引 4. 查询重写 ...

  7. oracle物化视图和表的区别,数据库中普通视图和物化视图有什么区别?

    对于增量刷新选项,如果在子查询中存在分析函数,则物化视图不起作用. Refresh方法- COMPLETE子句 完全刷新重新生成整个视图,如果请求完全刷新,oracle会完成 完全刷新即使增量刷新可用 ...

  8. 基于物化视图优化_「PostgreSQL技巧」PostgreSQL中的物化视图与汇总表比较

    多年来,物化视图一直是Postgres期待已久的功能.他们最终到达了Postgres 9.3,尽管当时很有限.在Postgres 9.3中,当刷新实例化视图时,它将在刷新时在表上保持锁定.如果您的工作 ...

  9. 普通视图和物化视图区别

    物化视图是一种特殊的物理表,"物化"(Materialized)视图是相对普通视图而言的.普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL语 ...

  10. drop 很慢 物化视图_物化视图问题-效率捉摸不定

    问题: 物化视图在基表数据修改后未经提交就直接查询速度很慢,之后再提交也没有作用,必须要过一段时间才可恢复,具体见下测试,希望高手指点! --过程如下 CREATE MATERIALIZED VIEW ...

最新文章

  1. 浏览器HTTP缓存机制
  2. 总结XX餐饮收银项目中的得与失
  3. 2022有哪些不容错过的后端技术趋势
  4. python sort 部分元素_Python 简单排序算法-选择、冒泡、插入排序实现
  5. linux 日志切割 自带,[日志分割回滚] 使用linux自带的logrotate对nginx日志进行分割...
  6. (十四)三次样条插值
  7. ol+天地图+geoserver_天地图离线瓦片的打包与发布(GeoServer)
  8. NC工具的使用说明教程
  9. linux 根目录设置777,linux 把根目录设置成777权限的补救方法
  10. XML解析—开源XOM类库
  11. android修改渠道,Android 多渠道定制化打包
  12. IE浏览器打不开解决办法
  13. java+英尺英寸,身高英寸换算(身高换算成英尺英寸)
  14. 667应用题出题点预测
  15. linux精确匹配文件名,Linux基础知识之文件名匹配
  16. RuntimeError: grad can be implicitly created only for scalar outputs
  17. jenkins html插件,Jenkins插件HTML Publisher Plugin的使用
  18. 清空linux+history_linux清除history命令
  19. eclipse创建servlet,filter产生classnotfound错误
  20. 练习题:让用户提供半径,然后计算出对应圆的周长和面积

热门文章

  1. Mockplus原型设计工具介绍
  2. 使用树莓派打造家庭监控系统
  3. 烽火服务器下关闭超线程CPU的步骤(完整版)
  4. python输出dat格式_输出dat文件
  5. HTML指南针源码zip,指南针指标公式源码
  6. 学英语尽量不要从背词汇表开始
  7. java钟表动画_JavaFX实现简易时钟效果
  8. Vue中的filter过滤器是使用方法
  9. 什么是IPFS?(三)
  10. 打工人也不好惹!一份校招“恶霸”指南强势冲上GitHub热榜,一天暴涨 1000 星!