@@ -17,73 +17,6 @@ RowID 应当具备以下特性:
1717| 3. 用户可以控制是否开启此功能
1818|====
1919
20- == 实现说明
21- 在IvorySQL中系统列 ctid 字段代表了数据行在表中的物理位置,也就是行标识(tuple identifier),由一对数值组成(块编号和行索引),可以通过ctid快速的查找表中的数据行,这样和Oracle的RowID行为很相似,但是ctid值有可能会改变(例如update/ vacuum full等),因此ctid不适合作为一个长期的行标识。
22-
23- 我们选择了表的oid加一个序列值组成的复合类型来做为RowID值,其中的序列是系统列。如果RowID功能被开启,则在建表的同时创建一个名为table-id_rowid_seq 的序列。同时在heap_form_tuple构造函数中,为HeapTupleHeaderData 的长度增加8个字节,并标识td->t_infomask = HEAP_HASROWID 位来表示rowid的存在。
24-
25- 在开启了支持ROWID的GUC参数或建表时带上 WITH ROWID 选项,以及对普通表执行 ALTER TABLE … SET WITH ROWID 时会通过增加序列创建命令来创建一个序列。
26- ```
27- /*
28- * Build a CREATE SEQUENCE command to create the sequence object,
29- * and add it to the list of things to be done before this CREATE/ALTER TABLE
30- */
31- seqstmt = makeNode(CreateSeqStmt);
32- seqstmt->with_rowid = true;
33- seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
34- seqstmt->options = lcons(makeDefElem("as",
35- (Node *) makeTypeNameFromOid(INT8OID, -1),
36- -1),
37- seqstmt->options);
38- seqstmt->options = lcons(makeDefElem("nocache",
39- NULL,
40- -1),
41- seqstmt->options);
42- ```
43-
44- 同时为了快速通过RowID伪列查询到一行数据,默认会在表的RowID列上创建一个UNIQUE索引,以提供快速查询功能。
45-
46- RowID列做为系统属性列其实现是通过在 heap.c 中新增一个系统列来实现的。
47- ```
48- /*
49- * Compatible Oracle ROWID pseudo column.
50- */
51- static const FormData_pg_attribute a7 = {
52- .attname = {"rowid"},
53- .atttypid = ROWIDOID,
54- .attlen = -1,
55- .attnum = RowIdAttributeNumber,
56- .attcacheoff = -1,
57- .atttypmod = -1,
58- .attbyval = false,
59- .attalign = TYPALIGN_SHORT,
60- .attstorage = TYPSTORAGE_PLAIN,
61- .attnotnull = true,
62- .attislocal = true,
63- };
64- ```
65-
66- 在pg_class系统表中增加一个 bool 类型的字段 relhasrowid,用于标识建表时的 WITH ROWID选项,如果建表时带了WITH ROWID选项,则 relhasrowid为 t,否则为f。
67- 用户在执行 ALTER table … SET WITH ROWID/ WITHOUT ROWID 命令时,也会修改这个值。
68-
69- ```
70- /* T if we generate ROWIDs for rows of rel */
71- bool relhasrowid BKI_DEFAULT(f);
72- ```
73-
74- 在RowID的存储方面,如果启用了RowID 伪列功能,则在插入表之前 heap_form_tuple函数会根据参数TupleDesc 中tdhasrowid 是否为true 在 HeapTupleHeaderData 中增加8个字节来存储序列值。
75- 在heap_prepare_insert 函数中获取序列的nextval值,存在HeapTupleHeader 相应的位置。
76-
77- ```
78- if (relation->rd_rel->relhasrowid)
79- {
80- // Get the sequence next value
81- seqnum = nextval_internal(relation->rd_rowdSeqid, true);
82- // Set the HeapTupleHeader
83- HeapTupleSetRowId(tup, seqnum);
84- }
85- ```
86-
8720== 功能开启
8821
8922IvorySQL提供了多种方式来开启RowID功能。
@@ -92,7 +25,6 @@ IvorySQL提供了多种方式来开启RowID功能。
9225
9326在IvorySQL 的兼容Oracle 模式下,可以通过 set ivorysql.default_with_rowids to on 来开启RowID,这个参数默认值为off。打开后创建的表,默认就带有了RowID列,可以通过 \d+ 表名 来查看。
9427
95- 在当前sesssion 中,如果这个GUC参数为 on,所有创建的表都将带上RowID列。
9628```
9729ivorysql=# show ivorysql.default_with_rowids;
9830 ivorysql.default_with_rowids
@@ -112,7 +44,7 @@ Access method: heap
11244```
11345=== 通过建表语句中增加 WITH ROWID 选项开启
11446
115- 在建表语句中增加 WITH ROWID 选项。 用户可以选择在需要的表上带有这个选项,没有WITH ROWID选项,将会创建一个普通的表。
47+ 用户可以选择在需要的表上带有这个选项,没有WITH ROWID选项,将会创建一个普通的表。
11648
11749```
11850ivorysql=# create table t2(a int) with rowid;
0 commit comments