上周末学习了《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:

int4
square_int4 (int4 x)
{
return x * x;
}

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

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

PL/PGSQL:

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

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

pg_aggregate表

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

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

2.4 与操作符相关的系统表

pg_operator表

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

例子如下:

CREATE FUNCTION mypower(float8, float8) RETURNS float8 AS ’begin
return exp(ln($1) * $2);
end;’ LANGUAGE ’plpgsql’;
CREATE OPERATOR ** (
procedure = mypower,
leftarg = float8,
rightarg = float8 );
SELECT 44 ** 2, 81 ** 0.5;
?column? | ?column?
----------+----------
1936 | 9
(1 row)

2.5 与数据类型相关的表

pg_type表

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

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

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

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

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

CREATE TYPE point3 (
input = point3in,
output = point3out,
internallength = 24, -- space for three float8’s
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. Scala模式匹配和类型系统

    1.模式匹配比java中的switch case强大很多,除了值,类型,集合等进行匹配,最常见的Case class进行匹配,Master.scala有大量的模式匹配. Case "_&qu ...

  2. Android判断网络是否已经连接

    // check all network connect, WIFI or mobile public static boolean isNetworkAvailable(final Context ...

  3. Hibernate 异常 —— Unable to instantiate default tuplize

    出现这个异常 —— Unable to instantiate default tuplizer ,是 Hibernate 的映射文件(*.hbm.xml)导致的.仔细检查一下工程里的映射文件吧. 笔 ...

  4. 标准类型内建函数 type()介绍

    我们现在来正式介绍一下 type().在Python2.2 以前, type() 是内建函数.不过从那时起,它变成了一个“工厂函数”.在本章的后面部分我们会讨论工厂函数, 现在你仍然可以将type() ...

  5. Mtk Android编译命令

    一.输入命令: cbk@YCS:~/work/k6/alps$ ./mk help Usage: (makeMtk|mk) [options] project actions [modules] Op ...

  6. PHP 日期格式:yyyy-MM-dd'T'HH:mm:ss.SSSZ 的写法

    今日在写一个接口是,其中有一个时间参数的格式是 yyyy-MM-dd'T'HH:mm:ss.SSSZ 查了一下最后的SSSZ SSS毫秒 Z代表时区 'T' 就是固定字符T,也有的指的是任意字符,本接 ...

  7. leetcode:Odd Even Linked List

    Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...

  8. java中参数传递

    一.参数是基本类型 相当于C++传值调用,方法中的形参是实参的副本. 二.参数是类类型 类类型的参数在方法调用中,相当于C++中的传址调用.形参是实参引用同一个对象.所有形参修改则实参也修改了 三.总 ...

  9. number-of-boomerangs

    https://leetcode.com/problems/number-of-boomerangs/ package com.company; import java.util.*; class S ...

  10. hdu4605 magic ball game 树状数组+离线处理

    题意:给你一棵二叉树,每个节点有一个w值,现在有一颗小球,值为x,从根节点往下掉,如果w==x,那么它就会停止:如果w>x,那么它往左.右儿子的概率都是1.2:如果w<x,那么它往左儿子的 ...