您正在查看: 标签 第一个 下的文章

索引访问方法接口定义索引的系统表记录

51.1. 索引的系统表记录

每个索引访问方法都在系统表pg_am里面用 一行来描述(参阅Section 45.3)。一个 pg_proc 行的主要内容是引用pg_proc里面的记录,用来标识索引访问方法提供的索引 访问函数。这些函数的接口(API)在本章后面描述。另外,pg_am的数据行生命了几个索引访问方法的固定属性,比如,它是否 支持多字段索引。目前还没有创建、删除pg_am 记录的特殊支持;任何想写这么一个新的访问方法的人都需要能够自己向这个 表里面插入合适的新行。

要想有真正用处,一个索引访问方法还必须有一个或多个 操作符类,定义在pg_opclass,pg_amop,pg_amproc 里面。这些记录允许规划器判断哪些查 询的条件可以适用于用这个索引访问方法创建的索引。操作符类在Section 35.14里面定义,是读取本章的前提之一。

一个独立的索引是由一行pg_class记录以物理关系的方式描述的,加上一个 pg_index行,表示该索引的逻辑内容 —也就是说,它所拥有的索引字段集,以 及被相关的操作符类捕获的这些字段的语义。索引字段(键值)可以是下层表的 字段,也可以是该表的数据哈工上的表达式。索引访问方法通常不关心索引的 键值来自何妨(它总是操作预处理完毕的键值),但是它会对 pg_index 里面的操作符类信息很感兴趣。所有这些表记录都可 以当作(Relation)数据结构的一部分访问,这个数据结构会在 对该索引的所有操作上都传递到对应的函数中。

pg_am 中的有些标志字段的含义并不那么直观。 amcanunique 的需求在Section 51.5里讨论过, amcanmulticol标志断言该索引访问方法支持多字段索引, amoptionalkey 断言它允许对那种在第一个索引 字段上没有给出可索引限制子句的扫描。如果 amcanmulticol为假,那么 amoptionalkey实际 上说的是该访问方法是否允许不带限制子句的全索引扫描。 那些支持多字段索引的访问访法必须支持那些在省略了除第一个字段以外的其它 字段的约束的扫描;不过,系统允许这些访问访法要求在第一个字段上出现一些 限制,这一点是通过把amoptionalkey设置为假 来实现的。amindexnulls断言该索引记录是为 NULL键值创建的。 因为大多数可以索引的操作符都是严格的,因此不能对NULL输入返回TRUE, 所以,第一眼看见会觉得不为NULL存储索引记录的想法很吸引人:因为他们不 可能被一个索引扫描返回。不过,这个想法在一个给出的索引字段上没有限制子 句的索引扫描的情况下就不行了;这样的扫描应该包括NULL行。实际上,这意 味着设置了amoptionalkey为真的索引必须索引 NULL,因为规划器可能会决定在根本没有扫描键字的时候使用这样的索引。这 样的索引必须可以在完全没有扫描键字的情况下运行。另外一个限制是一个支持 多字段索引的索引访问方法必须支持第一个字段后面的字段的NULL的索引,因 为规划器会认为这个索引可以用于那些没有限制这些字段的查询。比如,假设有 个索引在(a,b)上,而一个查询的条件是WHERE a = 4。 系统会认为这个索引可以用于扫描 a = 4的数据行, 如果索引忽略了 b 为空的数据行,那么就是错误的。不过,如果第一个索引字段 值是空,那么忽略它是 OK 的。因此,只是在索引访问方法索引了所有行,包括 任意NULL的组合,之后,amindexnulls才可以 设置为真值。 指向amindexnulls的一个变址存取方法 也会指向amsearchnulls,这表示它支持设置 为空和不为空子句为搜索条件。

系统表pg_inherits

45.23. pg_inherits

pg_inherits记录关于表继承层次的信息。 数据库里每个直接的子系表都有一条记录。间接的继承可以通过追溯记录链来判断。

Table 45-23. pg_inherits Columns

名称类型引用描述
inhrelidoidpg_class.oid 子表的OID
inhparentoidpg_class.oid 父表的OID
inhseqnoint4如果一个子表存在多个直系父表(多重继承),这个数字表明此继承字段的排列顺序。计数从1开始。

系统表pg_index

45.22. pg_index

pg_index 包含关于索引的一部分信息。 其它的信息大多数在pg_class.

Table 45-22. pg_index Columns

名称类型引用描述
indexrelidoidpg_class.oid这个索引在pg_class里记录的OID
indrelidoidpg_class.oid使用这个索引表在pg_class里的记录的OID
indnattsint2索引中的字段数(复制的pg_class.relnatts)
indisuniquebool如果为真,这是个唯一索引
indisprimarybool 如果为真,该索引代表该表的主键。这个字段为真的时候indisunique应该总是为真。
indimmediatebool 如果该值为真,立即执行唯一性检查,在插入 ( indisunique应始终是真,当这是真时)
indisclusteredbool 如果为真,那么该表最后簇聚在这个索引。
indisvalidbool 如果为真,那么该索引对于查询当前是有效的。如果为假,那么该索引可能不完整,仍然必须在INSERT/UPDATE操作时进行更新,不过不能安全的用于查询。如果是唯一索引,那么唯一属性也将不为真。
indcheckxminbool 如果为真,查询不能使用索引,直到 pg_index行的 XMIN低于其 TransactionXmin 事件视界,因为表可能包含它们可以看到坏热链的不兼容的行。
indisreadybool 如果为真,该索引目前为插入做好准备。False表示通过INSERT/UPDATE操作必须忽略索引。
indkeyint2vectorpg_attribute.attnum 这是一个包含indnatts值的数组,这些数组值表示这个索引所建立的表字段。比如一个值为1 3 的意思是第一个字段和第三个字段组成这个索引键字。这个数组里的零表明对应的索引属性是在这个表字段上的一个表达式,而不是一个简单的字段引用。
indclassoidvectorpg_opclass.oid 对于索引键字里面的每个字段,这个字段都包含一个所使用操作符类的OID 。参阅pg_opclass获取细节。
indoptionint2vector 这是一个存储每列标志位的indnatts值的数组 。位的含义是指由索引访问的方法。
indexprstext 表达式树(以nodeToString()形式表示)用于那些非简单字段引用的索引属性。 它是一个列表,在indkey里面的每个零条目一个元素。如果所有索引属性都是简单的引用,则为空。
indpredtext 部分索引断言的表达式树(以nodeToString()的形式表示)。如果不是部分索引,则为空。

系统表pg_cast

45.10. pg_cast

pg_cast表存储数据类型转换路径,包括内置路径和那些通过CREATE CAST定义的路径。

应当指出,pg_cast并不代表 系统知道如何执行的每一个类型转换,只有那些 不能从一些通用规则推导出的。例如, 在域和它的基类型之间转化没有明确表示在pg_cast。另一个重要例外是"自动I/O转换"。 执行使用数据类型的I/O函数到转换到text或其它字符串类型, 没有明确表示在pg_cast。

Table 45-10. pg_cast Columns

名称类型引用描述
castsourceoidpg_type.oid源数据类型的OID
casttargetoidpg_type.oid目标数据类型的OID
castfuncoidpg_proc.oid 用于执行这个转换的函数的OID。如果这个转换方法不需要函数,那么为零
castcontextchar 标识这个转换可以在什么环境里调用。e表示只能进行明确的转换(使用CAST或::语法)。 a表示在赋值给目标字段的时候隐含调用,也可以明确调用。i表示在表达式中隐含,当然也包括其它情况。
castmethodchar 说明转换是怎么运行的。f意味着在castfunc字段中应用的规定函数。i意味着输入输出函数被应用。b 意味着类型是二进制的 因此不要求转换。

在pg_cast里列出的类型转换函数必须总是以类型转换的源类型作为它的第一个参数类型, 并且返回类型转换的目的类型作为它的结果类型。一个类型转换函数最多有三个参数。 如果出现了第二个参数,必须是integer类型;它接受与目标类型关联的修饰词,如果没有,就是-1。 如果出现了第三个参数,那么必须是boolean类型;如果该类型转换是一种明确的转换, 那么它接受true,否则接受false。

在pg_cast里创建一条源类型和目标类型相同的记录是合理的, 只要相关联的函数接受多过一个参数。这样的记录代表"长度转换函数", 他们把该类型的数值转换为对特定的类型修饰词数值合法的值。

如果一条pg_cast记录有着不同的原类型和目标类型,并且有一个接收多于一个参数的函数, 那么它就意味着用一个步骤从一种类型转换到另外一种类型,同时还附加一个长度转换。 如果没有这样的记录,那么转换成一个使用了类型修饰词的类型涉及两个步骤, 一个是在数据类型之间转换,另外一个是附加修饰词。

Server Programming InterfaceSET TRANSACTION

SET TRANSACTION

Name

SET TRANSACTION -- 设置当前事务的特性

Synopsis

SET TRANSACTION transaction_mode [, ...]
SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]

where transaction_mode is one of:
这里的transaction_mode是下列之一:
ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }READ WRITE | READ ONLY

描述

SET TRANSACTION命令为当前事务设置特性。它对
后面的事务没有影响。SET SESSION CHARACTERISTICS
为一个会话中随后的每个事务设置缺省的隔离级别。这些缺省可以被
SET TRANSACTION为一个独立的事务覆盖。

可用的事务特性是事务隔离级别和事务访问模式(读/写或者只读)。

事务的隔离级别决定一个事务在同时存在其它并发运行 的事务时它能够看到什么数据:

READ COMMITTED

一条语句只能看到在它开始之前的数据。这是缺省。

SERIALIZABLE

当前事务中的所有语句只能看到在这次事务第一条查询或者修改数据 的语句执行之前的数据。

SQL标准还定义了另外两个级别,READ UNCOMMITTED 和REPEATABLE READ。在PostgreSQL 里READ UNCOMMITTED被当作READ COMMITTED, REPEATABLE READ被当作SERIALIZABLE。

事务隔离级别在事务中第一个数据修改语句(SELECT、 INSERT、 DELETE、 UPDATE、FETCH或者 COPY)执行之后就不能再次设置。参阅 Chapter 13 获取有关事务隔离级别和并发性控制的更多信息。

事务访问模式决定事务是读/写还是只读。读/写是缺省。如果一个事务是 只读,而且写入的表不是临时表,那么下面的SQL命令是不允许的: INSERT、UPDATE、 DELETE和 COPY FROM ; 而所有的CREATE、ALTER和 DROP; COMMENT, GRANT、REVOKE, TRUNCATE和EXPLAIN ANALYZE 以及EXECUTE都不允许。这是一个高层次的只读概念, 它并不阻止所有对磁盘的写入。

注意

如果执行SET TRANSACTION之前没有执行 START TRANSACTION或BEGIN, 那么它会显得没有效果一样,因为事务将立即结束。

可以用在BEGIN或START TRANSACTION 里面声明所需要的transaction_modes的 方法来避免使用 SET TRANSACTION 。

会话的缺省事务隔离级别也可以通过设置配置参数 xref linkend="guc-default-transaction-isolation"> 和default_transaction_read_only的方法来 设置(实际上SET SESSION CHARACTERISTICS只是 一个用SET来设置这些参数的冗长等效物)。这就意味着 缺省值可以通过ALTER DATABASE或在配置文件里等方法设置。 参考Chapter 18获取更多信息。

兼容性

两个命令都在SQL标准里定义了。SQL里的缺省事务隔离级别是 SERIALIZABLE;但在PostgreSQL里,缺省隔离级别 是READ COMMITTED,但是你可以用上面描述的方法 修改它。因为缺少谓词锁定SERIALIZABLE级别并非 真正的可串行化。参阅Chapter 13获取细节。

在SQL标准里还有另外一种事务特性可以用这些命令设置:诊断范围的大小。 这个概念只用于嵌入式SQL,因此没有在PostgreSQL 服务器里实现。

SQL标准要求在相连的transaction_modes 之间使用逗号,但是因为历史原因,PostgreSQL允许省略这个逗号。