《A Tour of PostgreSQL Internals》学习笔记——系统表和数据类型
上周末学习了《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》学习笔记——系统表和数据类型的更多相关文章
- 《A Tour of PostgreSQL Internals》学习笔记——进程间通信
中秋节假期这么快就没了,这几天还一直下雨,索性在家看看书.这次看的是Tom Lane的<A Tour of PostgreSQL Internals>.这篇小随笔就算做学习笔记了.园子里面 ...
- 《A Tour of PostgreSQL Internals》学习笔记——查询处理分析
终于要迎来postgresql的<A Tour of PostgreSQL Internals>系列的最后一篇了.学习是不能拖延的事儿,越拖延事情越多.不废话,一起来看看吧~ ...
- Mysql学习笔记(一)数据类型
原文:Mysql学习笔记(一)数据类型 学习内容: Mysql基本数据类型. 1.数字类型.. i.整型 Mysql数据类型 含义(有符号) tinyint(m ...
- Mysql学习笔记(二)数据类型 补充
原文:Mysql学习笔记(二)数据类型 补充 PS:简单的补充一下数据类型里的String类型以及列类型... 学习内容: 1.String类型 2.列类型存储需求 String类型: i.char与 ...
- JavaSE学习笔记(1)---数据类型、运算符、控制结构
javaSE学习笔记(1) 数据类型和运算符 1.注释可以提高程序的可读性.可划分为 单行注释 // 多行注释 /.../ 文档注释 /**...*/ 2.标识符的命名规则: 标识符必须以字母.下划线 ...
- Spring学习笔记2——表单数据验证、文件上传
在上一章节Spring学习笔记1——IOC: 尽量使用注解以及java代码中,已经搭建了项目的整体框架,介绍了IOC以及mybatis.第二节主要介绍SpringMVC中的表单数据验证以及文件上传. ...
- AngularJS 1.2.x 学习笔记(表单校验篇)
https://my.oschina.net/cokolin/blog/526911 摘要: 本文首发于 blog.csdn.net/vipshop_ebs/article/details/39472 ...
- Bootstrap学习笔记(二) 表单
在Bootstrap学习笔记(一) 排版的基础上继续学习Bootstrap的表单,编辑器及head内代码不变. 3-1 基础表单 单中常见的元素主要包括:文本输入框.下拉选择框.单选按钮.复选按钮.文 ...
- JavaScript学习笔记(一)——数据类型和变量
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
随机推荐
- ext3grep
- Java-J2SE学习笔记-树状展现文件结构
1.利用java.io相关类树状展现文件结构 2.判定给定路径是否为dir,是则递归,每一递归一层缩进一次 3.代码 package Test; import java.io.File; public ...
- MongoDB使用SSL
1. MongoDB对SSL的支持情况 MongoDB社区版本不支持SSL,企业版提供对SSL的支持.MongoDB源代码中包含SSL的实现,可以自己编译带SSL的MongoDB. MongoDB支持 ...
- C语言预处理程序[转]
c语言预处理程序有三种,分别是: 1.包含头文件,如:#include <stdio.h> 2.宏定义(本质是字符串的替换) 如 :#define 宏名 串(宏体) #define ...
- WordPress主题制作教程8:自定义page模版
创建新文件,头部注释 <?php /* Template Name: 新的page模版 */ ?> 在页面编辑右栏体现:
- HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)
Seam Carving DescriptionFish likes to take photo with his friends. Several days ago, he found that s ...
- js学习之道:表单验证公共js
/** 文件名称:CommonUtil.js 作者 : Yuce 编制时间: 2010-03-24 文件内容:一些常用的js公用类.工具类 包括方法: g_FormFieldIsNull 判断 ...
- [2014-03-13 08:46:42 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace. 问题提示 ...
- 计算机术语install和setup的区别
作为安装程序的Setup文件是软件的开发者专门为其软件设计的.exe文件,是当前最为盛行的安装程序.在运行该Setup文件进行软件安装时,Setup除了进行复制.改名.解压和目录维护等基本安装工作外, ...
- Mysql中的Prepared Statement与Stored Precedure学习
可以参考: http://stackoverflow.com/questions/196652/prepared-statement-vs-stored-procedure They are not ...