問題來源: 今天群里有人問:tableoid欄位在每行都有,而且一個表裡面的值是重覆的,這樣不合理...... 因此做了一些分析: 1)創建了一個表 2)查看該表的所有欄位 包括隱藏的: 可以發現有6個隱藏的欄位,其中cmax xmax cmin xmin都跟事物有關,在PG事物處理相關文章中可以經 ...
問題來源:
今天群里有人問:tableoid欄位在每行都有,而且一個表裡面的值是重覆的,這樣不合理......
因此做了一些分析:
1)創建了一個表
apple=# \d test_time Table "public.test_time" Column | Type | Modifiers --------+-----------------------------+----------- id | integer | date | timestamp without time zone |
2)查看該表的所有欄位 包括隱藏的:
apple=# select * from pg_attribute where attrelid in (select oid from pg_class where relname = 'test_time'); attrelid | attname | atttypid | attstattarget | attlen | attnum | attndims | attcacheoff | atttypmod | attbyval | attstorage | attalign | attnotnull | atthasdef | attisdropped | attislocal | attinhcount | attcollation | attacl | attoptions | attfdwoptions ----------+----------+----------+---------------+--------+--------+----------+-------------+-----------+----------+------------+----------+------------+-----------+--------------+------------+-------------+--------------+--------+------------+--------------- 33433 | tableoid | 26 | 0 | 4 | -7 | 0 | -1 | -1 | t | p | i | t | f | f | t | 0 | 0 | | | 33433 | cmax | 29 | 0 | 4 | -6 | 0 | -1 | -1 | t | p | i | t | f | f | t | 0 | 0 | | | 33433 | xmax | 28 | 0 | 4 | -5 | 0 | -1 | -1 | t | p | i | t | f | f | t | 0 | 0 | | | 33433 | cmin | 29 | 0 | 4 | -4 | 0 | -1 | -1 | t | p | i | t | f | f | t | 0 | 0 | | | 33433 | xmin | 28 | 0 | 4 | -3 | 0 | -1 | -1 | t | p | i | t | f | f | t | 0 | 0 | | | 33433 | ctid | 27 | 0 | 6 | -1 | 0 | -1 | -1 | f | p | s | t | f | f | t | 0 | 0 | | | 33433 | id | 23 | -1 | 4 | 1 | 0 | -1 | -1 | t | p | i | f | f | f | t | 0 | 0 | | | 33433 | date | 1114 | -1 | 8 | 2 | 0 | -1 | -1 | t | p | d | f | f | f | t | 0 | 0 | | | (8 rows)
可以發現有6個隱藏的欄位,其中cmax xmax cmin xmin都跟事物有關,在PG事物處理相關文章中可以經常看到。
恰好前段時間研究PG表去重覆數據用過ctid,物理地址塊上的編號,因此今天再來學習一下tableoid。
3)初步分析結果:
A. 存磁碟的時候,數據是一行一行的存儲,有必要知道該行數據屬於哪個表。(那麼如果支持列存儲的話,確實可以對這些數據進行壓縮了,只存一條即可。)
B. 繼承表的情況,知道數據是在哪個子表裡面。
4)視圖不會有預設欄位:
apple=# select * from pg_attribute where attrelid in (select oid from pg_class where relname in (select viewname from pg_views)) and attnum < 0; attrelid | attname | atttypid | attstattarget | attlen | attnum | attndims | attcacheoff | atttypmod | attbyval | attstorage | attalign | attnotnull | atthasdef | attisdropped | attislocal | attinhcount | attcollation | attacl | attoptions | attfdwoptions ----------+---------+----------+---------------+--------+--------+----------+-------------+-----------+----------+------------+----------+------------+-----------+--------------+------------+-------------+--------------+--------+------------+--------------- (0 rows)
5)以後想查看表的oid再也不用去pg_class裡面找了:
apple=# select tableoid from test_time; tableoid ---------- 33433 (1 row)
搞了半天發現也沒啥,白折騰了......
參考消息:
每個表都有幾個系統欄位,這些欄位是由系統隱含定義的。 因此,這些名字不能用於用戶定義的欄位名。 (請註意這些限制與這個名字是否關鍵字無關;把名字用引號括起來並不能讓你逃離這些限制。) 你實際上不需要註意這些欄位,只要知道它們存在就可以了。 oid 行的對象標識符(對象 ID)。這個欄位只有在創建表的時候使用了 WITH OIDS,或者是設置了配置參數 default_with_oids 時出現。 這個欄位的類型是 oid(和欄位同名); 參閱Section 8.12 獲取有關這種類型的更多信息。 tableoid 包含本行的表的 OID。這個欄位對那些從繼承層次中選取的查詢特別有用(參閱 Section 5.8), 因為如果沒有它的話,我們就很難說明一行來自哪個獨立的表。 tableoid 可以和pg_class 的 oid 欄位連接起來獲取表名字。 xmin 插入該行版本的事務的標識(事務 ID)。(註意:在這個環境里, 一個行版本是一行的一個狀態;一行的每次更新都為同一個邏輯行創建一個新的行版本。) cmin 在插入事務內部的命令標識(從零開始)。 xmax 刪除事務的標識(事務ID),如果不是被刪除的行版本,那麼是零。 在一個可見行版本里,這個欄位有可能是非零。這通常意味著刪除事務還沒有提交, 或者是一個刪除的企圖被回滾掉了。 cmax 在刪除事務內部的命令標識符,或者是零。 ctid 一個行版本在它所處的表內的物理位置。請註意,儘管 ctid 可以用於非常快速地定位行版本,但每次 VACUUM FULL 之後, 一個行的 ctid 都會被更新或者移動。 因此 ctid 是不能作為長期的行標識符的。 應該使用OID,或者更好是用戶定義的序列號,來標識一個邏輯行。