上周末学习了《A Tour of PostgreSQL Internals》的第一部分(View 1),今天我们继续打开书本,继续View 2 部分。

View 2 Postgresql的系统表和数据类型

和其他大多数DBMS相比,postgresql在更大程度上使用了“ 数据驱动 ”。

为什么这么说呢?

按照Tom Lane的解释,原因如下:

  • postgresql使用一套系统表描述数据库表,表中的每一列,每个索引等等;
  • 除此以外,postgresql同样使用系统表存储数据类型、函数、操作符和索引的访问方法等等信息;
  • 通过增加新的数据字典,postgresql可以很方便的扩展。

我们知道,在关系数据库中,为了数据库系统的控制,必须提供数据字典的功能。数据字典不仅存储各种对象的描述,而且存储这些数据对象的细节信息。其中系统表是Postgresql数据库存放结构元数据的地方,表现为存放有系统信息的普通表和视图。

在postgresql每一个数据库中都有单独的一套系统表,这些表大多是在数据库创建时从template数据库拷贝过来的,描述该数据库的属性。

如果想看源码的话,可以看看src/include/catalog目录下的"pg_xxx.h"文件,这些文件相应地定义了"pg_xxx"系统表的数据结构。另外,indexing.h文件定义了所有的系统表索引,toasting.h定义了所有系统表的TOAST表。


2.1 基本系统表

pg_class表

pg_class存储表以及与表结构类似的数据库对象的信息,包括索引、序列、试图、复合数据类型、TOAST表等等。每一个对象在pg_class表中都表现为一个元组,并且分配一个OID作为唯一标识(该属性作为隐藏属性,不能直接访问)。

pg_attribute表

pg_attribute表存储数据库表中的每个属性的信息,对于表的每一个属性,都有一个对应的元组描述其属性,例如属性名、属性的数据类型、默认值、非NULL约束等等。

pg_index表

pg_index表存储索引的具体信息,把索引和索引对应的表关联起来。这里需要说明的是,由于索引也是表,所以索引也在pg_class表和pg_attribute表中有对应的元组。因此,pg_index表中的每个元组包含索引在pg_class表中对应的元组的OID和基础表(即索引建立在该表上)的OID,同时,也包含了计算索引所使用的表的列的信息以及索引的运算表达式。

以上是postgresql数据库中最重要的三张系统表,还有很多其他的表就不在此一一列出了,比如pg_tablespace、pg_database等等。这些表的信息可以通过select语句来获取。

2.2 与函数相关的系统表

pg_proc表

pg_proc表对函数进行了定义。每一个函数在该表中都对应一个元组,包含函数名。输入参数类型,返回类型以及对函数的定义(可能是文本,可能是一段编译型语句,也可能是对可执行代码的引用)。编译过的函数可以静态地链接到服务器上,或者在存储在共享库内,当第一次使用该库时动态的载入。这些编译过的函数一般都使用C编写,当然理论上你可以有别的选择。

pg_language表

pg_language表定义了函数实现所使用的语言。主要支持了C语言和SQL语句。一些可选的语言包括pl/pgsql、tcl和perl。这些语言是由动态链接的处理程序提供支持的,服务器内核并不关注,只负责调用。

以下是一些示例函数:

C:

  1. int4
  2. square_int4 (int4 x)
  3. {
  4. return x * x;
  5. }

把上面的函数编译成共享库文件,这样声明:

  1. CREATE FUNCTION square(int4) RETURNS int4
  2. AS ’/path/to/square.so’, square_int4
  3. LANGUAGE C’;

PL/PGSQL:

  1. CREATE FUNCTION square(int4) RETURNS int4 AS begin
  2. return $1 * $1;
  3. end;’ LANGUAGE plpgsql’;

2.3 与聚集函数相关的系统表

pg_aggregate表

pg_aggregate表定义了我们熟悉的这些聚集函数,比如:min()、max()、count()等。每个聚集函数涉及一个运行时的数据类型,一个更新函数,一个最终输出函数,共同完成了一个聚集函数的功能。

  1. -- The working state is a 2-element integer array, sum and count.
  2. -- We use split(n) as a quick-and-dirty way of parsing the input array
  3. -- value, which comes in as a string like ’{1,2}’. There are better ways...
  4. create function tcl_int4_accum(int4[], int4) returns int4[] as
  5. set state [split $1 "{,}"]
  6. set newsum [expr {[lindex $state 1] + $2}]
  7. set newcnt [expr {[lindex $state 2] + 1}]
  8. return "{$newsum,$newcnt}"
  9. language pltcl’;
  10. create function tcl_int4_avg(int4[]) returns int4 as
  11. set state [split $1 "{,}"]
  12. if {[lindex $state 2] == 0} { return_null }
  13. return [expr {[lindex $state 1] / [lindex $state 2]}]
  14. language pltcl’;
  15. create aggregate tcl_avg (
  16. basetype = int4, -- input datatype
  17. sfunc = tcl_int4_accum, -- update function name
  18. stype = int4[], -- working-state datatype
  19. finalfunc = tcl_int4_avg, -- final-output function name
  20. initcond = ’{0,0}’ -- initial value of working state
  21. );

2.4 与操作符相关的系统表

pg_operator表

很显然,该表定义了表达式中能使用的运算符。这种运算符更多的是一种“语法糖”,将只有一两个参数的函数变成操作符,简化了书写和操作。

例子如下:

  1. CREATE FUNCTION mypower(float8, float8) RETURNS float8 AS begin
  2. return exp(ln($1) * $2);
  3. end;’ LANGUAGE plpgsql’;
  4. CREATE OPERATOR ** (
  5. procedure = mypower,
  6. leftarg = float8,
  7. rightarg = float8 );
  8. SELECT 44 ** 2, 81 ** 0.5;
  9. ?column? | ?column?
  10. ----------+----------
  11. 1936 | 9
  12. (1 row)

2.5 与数据类型相关的表

pg_type表

该表定义了表中属性存储、操作符和函数接收和返回所使用的基本数据类型。如果想增加自己需要的数据类型,可以通过在pg_type表中增加相应的元组实现。

例如你要一种能存储3维空间点的数据类型,而postgresql内置的类型只支持到2维的点,那么你可以自己定义一种3维点的数据类型。对于一个数据类型而言,你至少需要定义两个相关函数:

1.把外部输入文本转换为你的数据类型

2.把你的数据类型转换为外部文本

只有定义了这两个函数,你的数据类型才能够被正常的使用。

  1. CREATE TYPE point3 (
  2. input = point3in,
  3. output = point3out,
  4. internallength = 24, -- space for three float8s
  5. alignment = double ); -- ensure storage will be aligned properly

一般来说,你定义了一种新的数据类型之后,不仅仅只访问和存储它们,可能还需要其他一些有用的操作符和函数,对上面的例子来说,计算两个三维点之间的距离是很常见和必要的操作。

同时,如果你想让你的数据类型可以被索引,你还需要在pg_amop表和pg_amproc中增加相应的元组,以此告诉索引程序一系列复杂的操作符和函数操作你的数据类型后的行为结果,比如< <= = > >= 这样的操作符。同样,你需要在pg_am表中增加元组来支持对索引的访问。


小结

优点:

  • 优点显而易见,你可以很方便的扩展你需要的函数,数据类型,尤其对于你的某些特别的业务需求的时候,这是很方便和有利的。

缺点:

  • 正如你所看到的,增加一个数据类型,你需要做很多工作,在很多系统表中插入元祖,编写函数和数据类型定义等等,这需要一定的业务水平;
  • 对于函数而言,你需要了解数据的类型、访问方式以及优化方法,牵扯到系统的方方面面,你很容易将本来不相关的模块关联了起来,影响了系统的稳定性。

好的《A Tour of PostgreSQL Internals》的View 2 部分就是这样,还剩View 3部分,加油,争取这周搞定!也谢谢大家支持,欢迎讨论,有哪里理解不对的地方还请大家批评指正~

《A Tour of PostgreSQL Internals》学习笔记——系统表和数据类型的更多相关文章

  1. 《A Tour of PostgreSQL Internals》学习笔记——进程间通信

    中秋节假期这么快就没了,这几天还一直下雨,索性在家看看书.这次看的是Tom Lane的<A Tour of PostgreSQL Internals>.这篇小随笔就算做学习笔记了.园子里面 ...

  2. 《A Tour of PostgreSQL Internals》学习笔记——查询处理分析

           终于要迎来postgresql的<A Tour of PostgreSQL Internals>系列的最后一篇了.学习是不能拖延的事儿,越拖延事情越多.不废话,一起来看看吧~ ...

  3. Mysql学习笔记(一)数据类型

    原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型     Mysql数据类型             含义(有符号)     tinyint(m ...

  4. Mysql学习笔记(二)数据类型 补充

    原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与 ...

  5. JavaSE学习笔记(1)---数据类型、运算符、控制结构

    javaSE学习笔记(1) 数据类型和运算符 1.注释可以提高程序的可读性.可划分为 单行注释 // 多行注释 /.../ 文档注释 /**...*/ 2.标识符的命名规则: 标识符必须以字母.下划线 ...

  6. Spring学习笔记2——表单数据验证、文件上传

    在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...

  7. AngularJS 1.2.x 学习笔记(表单校验篇)

    https://my.oschina.net/cokolin/blog/526911 摘要: 本文首发于 blog.csdn.net/vipshop_ebs/article/details/39472 ...

  8. Bootstrap学习笔记(二) 表单

    在Bootstrap学习笔记(一) 排版的基础上继续学习Bootstrap的表单,编辑器及head内代码不变. 3-1 基础表单 单中常见的元素主要包括:文本输入框.下拉选择框.单选按钮.复选按钮.文 ...

  9. JavaScript学习笔记(一)——数据类型和变量

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

随机推荐

  1. linux环境几个特殊的shell变量

    特殊的shell变量: $0  获取当前执行的shell脚本的文件名 $n  获取当前执行的shell脚本的第n个参数值,n=1..9 $*  获取当前shell的所有参数 “$1 $2 $3 …注意 ...

  2. C语言运算符优先级表

    优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右   () 圆括号 (表达式)/函数名(形参表)   . 成员选择(对象) 对象.成员名   -& ...

  3. ffmpeg转码时对编码率和固定码率的处理

    http://www.rosoo.net/a/201107/14663.html 一般fps在代码里这样表示 Fps = den/num 如果den = 15,num=1,则fps = 15. 如果帧 ...

  4. 302. Smallest Rectangle Enclosing Black Pixels

    题目: An image is represented by a binary matrix with 0 as a white pixel and 1 as a black pixel. The b ...

  5. MSBuild和Jenkins搭建持续集成环境

    http://www.2cto.com/os/201409/334323.html http://my.oschina.net/anxuyong/blog/353897 http://www.cnbl ...

  6. [c/c++]指针数组 pk 数组指针

    首先强调 指针数组归根结底是个数组:数组指针归根结底是个指针. 数组指针 以int (*int)[10]为例 ()的优先级大于[],因此首先它是一个指针,它指向一个数组,数组的维数是10.因此数组指针 ...

  7. 【coursera笔记】Machine Learning(Week6)

    发现自己不写总结真是件很恶劣的事情,好多学的东西没有自己总结都忘记了.所以决定从今天开始,学东西的时候一定跟上总结. 我写的东西大多数是自己通俗的总结,不太喜欢写严格的定义或者证明,写了也记不住,欢迎 ...

  8. UVA 11019 Matrix Matcher(ac自动机)

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. [lintcode the-smallest-difference]最小差(python)

    题目链接:http://www.lintcode.com/zh-cn/problem/the-smallest-difference/ 给定两个整数数组(第一个是数组 A,第二个是数组 B),在数组 ...

  10. 我的ipad应用备份

    听歌: 网易云音乐,QQ音乐 摄影: CameraConnect,Replay,PhotoBooth,PhotoCollage,画中画相机,Creative Shape, 简拼,玩图,PicsArt, ...