红书推荐系列(四):The Design of Postgres

  INGRES于1975-1977年在加州大学开发,后来又做了分布式、抽象数据等一系列的扩展,但人们很快发现在INGRES现有的架构上很难添加一些新的功能,所以开发团队重新开发了Postgres,Postgre后来又被PostgreSQL取代。

   Postgres最大的贡献是abstract data type (ADT) system,在主流的数据库中添加用户定义类型和函数用的都是Postgres的模型。

设计目标

  Postgres设计时,关系型数据模型已经被证明非常适合商务数据处理,但是这种模型不适合市场上的许多软件(比如CAD中需要存储的图形和图形数据)。

  Postgres的第一个设计目标就是支持复杂对象。虽然复杂对象可以通过关系表模拟出来,但是这样性能往往是不可接受的。比如在传统的数据库中,创建物体有以下语句:

POLYGON(id, other fields)
CIRCLE(id, other fields)
LINE(id, other fields)

  要显示一个物体,还需要颜色、位置、缩放等信息。我们可以把它们存入一个表中:

DISPLAY(color, position, scaling, object-type, object-id)

  object-type指定对象在哪个表中(POLYGON、CIRCLE、LINE),object-id指定对象的标识符。那么我们每次取数据的时候都会遍历所有的表:

foreach OBJ in {POLYGON, CIRCLE, LINE} do
    range of O is OBJ
    range of D is DISPLAY
    retrieve (D.all, O.all)
    where D.object-id = O.id and D.object-type = OBJ

  显然,无论DBMS有多快,都不能实时的找到需要的所有结果,因为这样的查询可以任意多。

  第二个设计目标是扩展性。传统的DBMS只提供了少量的内置数据类型和访问方法。比如查找图形类型的数据,这时传统的B+树很难满足查找需求,而比较适合的K-D-R树和R树却比较适合。这就要求数据库能够提供易用的扩展接口。

  第三个目标是支持alerters、triggers和规则系统。

  第四个目标是减少DBMS在crash recovery的代码量。

  第五个目标是尽量使用最新技术。

  最后一个目标是减少对关系模型的修改。

POSTQUEL

  这一节介绍Postgres的查询语言。

数据定义

  Postgres提供了一些内置类型:

  1. 整数
  2. 浮点数
  3. 固长字符串
  4. 变长任意类型数组
  5. POSTQUEL
  6. procedure

  Scalar类型(1、2、3)可以通过点标记访问(EMP.name)。

  变长数组(4)通过下标访问(EMP.picture[i])。

  POSTQUEL包含一串数据操作命令,同样也是通过点标记访问。但是如果POSTQUEL中包含取数据命令,那么可以在命令后面继续加点标记(EMP.hobbies.battingavg)。

  Procedure包含用通用编程语言编写的程序。

  POSTQUEL和procedure都可以通过Execute命令来执行,比如有一个表:

EMP(name, age, salary, hobbies, dept)

  那么可以通过以下命令来执行查询:

EXECUTE(EMP.hobbies)
WHERE EMP.name = "Smith"

  因为命令包含的取得数据的命令可能不止一条,所以取得的tuple的类型可能不同(因此编程语言接口必须要提供动态决定类型的机制)。

Complex Objects

  Posgres的复杂对象可以通过POSTQUEL和procedure表示。以上面的POLYGON,CIRCLE,LINE为例,一个对象可以通过这些类型组成。首先,定义一个对象的定义为:

CREATE OBJECT(name=char[10], obj=postquel)

  那么我们定义一个苹果和一个橘子对象,如下:

Name OBJ
apple

RETRIEVE(POLYGON.all)

WHERE POLYGON.id = 10

RETRIEVE(CIRCLE.all)

WHERE CIRCLE.id = 40

orange

RETRIEVE(LINE.all)

WHERE LINE.id = 17

RETRIEVE(POLYGON.all)

WHERE POLYGON.id = 10

  通过定义procedure还可以支持更多的对象表示方法,比如对于上面的对象我们想要将它显示出来,那么创建对象的方法如下:

CREATE OBJECT(name=char[10], obj=postquel, display=cproc)

  cproc对于所有的OBJECT相同,所以不需要每个对象都存储一个,只存一个在系统表中即可。

  这一部分感觉paper讲的不是很全面,有兴趣的读者可以去PostgreSQL官网文档查找更详细的资料。

Time Varying Data

  POSTQUEL允许用户保存查询历史数据和版本。历史数据可以通过指定时间来访问,比如:

RETRIEVE(E.all)
FROM E IN EMP["7 January 2020"]

  命令取出了2020年1月7日的所有数据。

迭代查询、触发器、提醒、规则

  这里部分和PostgreSQL或者现代的其它DBMS在语法差别有点大,这里就略过了。

SYSTEM ARCHITECTURE

  不得不说,读这篇paper真的恼人,就像老太太的袜子一样,又长又臭。

Process Structure

  Postgre采用多进程模式查询数据,其好处可以看红书推荐系列(二)。

Query Processing

  Postgres的query optimizer比较传统,但做了三点扩展。第一,optimizer必须能利用用户定义的访问方法。第二,要一个有效通用的方法来支持POSTQUEL和procedure。第三,需要一个高效的方法来支持trigger和rules。

Support for New Types

  支持访问方法的基本思想是实现一些特定的运算符,比如在B-树中,需要的运算符为{<, =, >, >=, <=}。这些运算符符合一些基本定律,包括传递性。

Support for Procedural Data

   优化查询性能的方法是预计算和缓存结果。其中预计算的分为两步:

  1. 编译POSTQUEL命令的访问方案。
  2. 执行访问方案。

总结

   Postgres的SQL语法一言难尽,虽然已经到了80年代,但SQL语法设计仍然体现出一些糟糕的地方。总之,这篇paper最值得看的地方就是抽象数据是怎么样用关系型数据有效表示的,其它的部分就可有可无了。

posted @ 2020-11-03 16:07  Nanachi  阅读(236)  评论(0)    收藏  举报