本文是关于开发人员在谈论Postgres时使用的术语的一个非官方的或许还不太完整的介绍。
PART 1 Tuple(元组)
tuple是Postgres的一个基本的构建模块,故而它会经常在开发人员的谈论中出现。
tuple即大部分人理解的表中的行。它由一些列组成,每一列则由列名、列值和数据类型组成。
我们还会经常听到“Tuple set”,即为行集,也就是常说的表;或者,是类似于表的对象。稍后,我们还可以看到其他表示类似于表的对象的特殊词汇。
PART 2 Record(记录)与Row(行)
Record与Row是对Tuple的另一种说法,但与Tuple不同的是,record与row一般用户SQL查询中。
record关键字一般用于数据库服务端返回复合数据类型的函数的返回类型。
CREATE FUNCTION onerow(pk integer)
RETURNS record AS
$$
SELECT * FROM mytable WHERE mytable.pk = pk
$$
LANGUAGE 'sql';
row关键字用于在SQL中构建复合数据类型。
INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);
PART 3 Array(数组)
数组即为具有相同数据类型的值的列表。以下为整数数组的示例:
SELECT ARRAY[1,2,3,4];
数组还可以是多维的:
SELECT ARRAY[[1,2,3],[4,5,6]];
而且,数组不仅仅限于Postgres内置的数据类型,还可以用于自定义的类型:
CREATE TYPE person AS (name text, age integer);
SELECT ('Peter',45)::person;
SELECT ARRAY[('Peter',45),('Paul',35)]::person[];
PART 4 Relation(关系)
relation即为行的集合。单行为一元的关系,N行未N元的关系。
不过,通常来说,我们指的关系为“表”。
每个表均是关系,但反之不然。
视图也是关系的一种。
所以,实际上,关系为查询的结果。查询结果即为行集,其即为关系。即使查询的中间步骤,也可以看为一个关系。
而使用连接条件关联两张表得到的查询结果,也是一个关系!
可通过查看pg_class系统视图来直观感受下数据库中的关系:
SELECT relname, relkind FROM pg_class;
该查询列出了Postgres中的所有关系。其中,relkind为r的是表。结果中还包含索引、视图、序列、物化视图和外部表。
PART 5 Target List(目标列表)和Restrictions(限制条件)
随着对Postgres的深入了解,会发现一些不知道其名称的东西。例如,查询语句中,介于SELECT与FROM之间的叫什么?WHERE之后的叫什么?
SELECT <此为目标列表>
FROM mytable
WHERE <此为限制条件>
PART 6 Schema(模式)
模式类似于数据库中的一个文件夹。但实际上,Postgres内部使用命名空间(namespace)指代模式(schema)。可通过查询pg_namespace表查看数据库中的所有模式:
SELECT * FROM pg_namespace;
这还不是全部。当我第一次听到“模式”这个词时,我感到非常困惑,因为在我看来,“模式”是“数据库中表定义的集合”。因此,“应用程序模式”可能是数据库中用于支持特定软件应用程序的所有表。
因此,“模式”(SQL层面来说)是一个文件夹,可以在其中放置数据库对象(如表、函数等),而在Postgres中,也被称为“命名空间”,有时(对应用程序开发人员来说)是一个或多个表的定义。
PART 7 Page(页)
时间再久一些,就会经常听到pages这个词了。
万幸,pages是数据库内部的实现细节,对最终用户来说,是透明的。
而数据库管理员则需要对pages有一定的理解,因为有些优化参数会涉及到pages。
在磁盘层面,数据库表以文件形式存在,一个文件一个表(实际上,当表足够大的时候,会包含多个文件,此处暂时忽略这种情形)。
如果表中的每行数据都紧凑的装载到一个文件中,那么当数据变化的时候,数据库该如何变更它呢?
例如,将名字从Paul变更为Paul the Great,如果行紧凑存储,那么就需要扩展表,然后将Paul后的所有数据后移,以扩大空间。毫无效率可言!
这就有了页的概念。数据库在内部将表文件划分为规则间隔的“页”,并仅用元组填充每一页的部分(对此有另一个术语,即“填充因子”),而不是使用一个紧密填充的数据文件。现在,当数据库需要更新一个元组(可能要添加更多数据)时,只需要重写相关的页,而文件的其余部分则可以保持不变。
“页”在许多方面都是底层数据库引擎的基本单元。在编写SQL时看不到它,但是像“页缓存”(一块RAM,用于高速访问频繁读取的页)和“随机页成本”(一个表示在文件内随机访问所耗成本的调优参数)等证明了“页”在数据库系统设计中的中心地位。PostgreSQL页固定为8192字节。这也是WAL等的内存“块”的默认大小。有些块大小可以调整;但页不可以。
PART 8 Toast
"Are those objects toasted?"
他们在说什么?是要把数据库对象烤了吃掉么?
而实际上,Toast在Postgres中,是“The Oversized-Attribute Storage Technique”的缩写,表示超限属性存储技术。
还记得Postgres中页的存储构建方式么?是的,它们是固定大小的8kb,那么如果存储超过8kb的记录,会发生什么呢?那我们就遇到了超限属性的问题。
与页类似,Toast也是对最终用户透明的技术。当输入的属性超过页的大小时,Postgres会将其切分为小块以适应页的大小,并将它们放到一个与主表关联的Toast表中。
-- Find the toast table associated with a user visible table
SELECT a.relname, b.relname AS toast_relname
FROM pg_class a
JOIN pg_class b
ON a.reltoastrelid = b.oid
WHERE a.relname = 'mytablename';
然后,当查询涉及到该元组时,数据库会检索Toast表中的数据,并将其合并后返回。
故而,检索被Toast的数据比检索普通的数据,需要消耗更多的时间。
PART 9 结论
本文仅含部分专业术语,期望不久的将来,可发布更多的专业术语释义。
来源:开源软件联盟PostgreSQL分会
链接:https://mp.weixin.qq.com/s/cGyvDOe0fHYVogW9LgaZBg