OK PostgreSQL 的菜单上也有一个叫 Materialized views 的功能,同时PG 也有一个表 inheritance 的东西。而这两样东西可以解决数据应用中的很多问题。那怎么来应用PG 提供的这两个功能。
举例:一个系统中,每天都要出一个查询结果,而这个查询的结果只要,当前当前某位导演导演的电影,并且截止为电影上映期距今2年前
select *
from film_actor as fa
left join film as fi on fa.film_id = fi.film_id
where fa.actor_id = 4 and fi.last_update < now() - interval '2 year';
如果这个数据每天都有人查,但其实这个数据可以认为是一个静态的数据,那我们用物化视图就再好不过了,我们可以建立一个物化视图,在每天的早上1点来刷新物化视图,而这一天的所有关于这个数据的查询全部可以走我们建立的物化视图。
create materialized view movie_actor as
select fi.title,fi.description,fi.release_year
from film_actor as fa
left join film as fi on fa.film_id = fi.film_id
where fa.actor_id = 4 and fi.last_update < now() - interval '2 year';
同时我们可以手动来刷新视图,通过命令 refresh materialized view movie_actor;
但这里有一个问题是如果使用 refresh materialized view 命令会阻塞物化视图对应表的包括 select 操作在内的使用,如果刷新的比较快,则这不是一个问题,但PG 给了另外一个选择,来避免这个问题
refresh materialized view concurrently movie_actor;
对添加参数 concurrently 来并行的进行数据的更新,但前提是如果使用这个参数你的视图需要建立一个唯一的索引来帮助命令的运行。
举例我们可以创建一个带有查询条件的表,并且在这个物化视图中是有一列有唯一值的。
create materialized view film_view as select film_id,title,last_update from film where title like 'A%';
create unique index ix_film_file_id on film_view (film_id);
refresh materialized view concurrently film_view;
说完物化视图,可能有些人觉得这个功能,怎么不能实时更新视图
其实我是这样看这个问题的,如果物化视图是实时更新的,这对系统来说压力会比较大,并且未必会比你建立一个 VIEW 或者直接查询要好,或许性能更糟糕。
而要解决一个实时性的问题,其实我们可以使用PG 独有的继承的概念和功能
OK 既然提到头脑风暴,我们可以扩大范围想一想程序设计展现到表上有没有一种设计叫不断的加列,不断的扩展,最后扩展到 800列的情形,(画外音,800列,你疯了吧),我没疯,我曾经管理过一个长达800列的单表上几个T 的怪表。当然当我接手的时候,第一句就是,这 ta ma 那个鬼设计的表,后来经过了解,原来是历史原因,没有人管理,开发肆意妄为的产物。
那如果我们遇到这样的情况,业务活动频繁,并且一直要加列,而有些有年代感的列,其实早就不用了,有些因为业务需要加上那么几个月。你能怎么办,如我曾经的一篇文字,你不让人家加,人家怼你,凭什么不让加,不加活干不了,你负责。所以说规则化的 DBA 越来越被鄙视,被怼,因为你光定规则了,你说不清为什么要定这个规则,你也拿不出解决方案,只是告诉人家不能,不怼你怼谁 !
OK 头脑风暴到此为止,如果此时我拥有了PG ,那我怎么办,好办,要凉拌有凉拌,要热炒有热炒。
下面只需要三步,你就能让开发心服口服
1 你的字段使用的期限是多长,是仅仅临时的业务,还是长久的业务
2 你的业务类型是什么,你加的字段是服务 A 业务 还是 B 业务 ,或者C 业务
3 你查询是否会比较频繁
问完以后,你根据PG的继承表就应该有一个思路, 举例我们有一个订单表(当然这个订单表漏洞百出)
现在由于业务需求,增加了一些业务,而这些业务与原来的表的业务一部分数据是重合的,但这些新业务的数据又需要增加大量的字段,此时该怎么办
1 在原表上增加新的字段,但是问题是,老的业务不需要这些字段,那意味着原表上有不少字段就是 NULL
2 建立新表,存储新的数据,但有的时候需要统计一些信息,新老业务都需要。
此时我可以使用PG 的继承表来解决这个问题,上图我们已经建立了一个基础的业务表。
下面我需要建立继承表,并且在继承表中插入数据
结果我们可以看到,里面仅仅有刚输入的数据,而我们反过头来看看 原表里面有什么,在原表里面有继承表的数据。
可能看到这里,我觉得我需要画一个图来讲一下这个继承表,看到下面的图你是不是想到了,MYSQL 的 分表,以及分表后的数据汇总。PG 一步完成你的需求。
1 继承表里面的数据是在基础表的基础上进行扩展
2 继承表里面的数据会汇聚到基础表
3 修改继承表里面的数据,基础表对应的数据会进行变化
4 修改基础表中对应继承表的数据,继承表的数据也会变化
这是一个非常好的功能,相当于给这些表建立了trigger 相关insert, update delete ,truncate , drop 的操作都会对原有的数据在继承表和原表之间产生关联。
所以如果在理解某些业务需求和背景的同时,又掌握了某些特殊的数据库技术,那就会降低开发的成本提高开发效率。