數(shù)據(jù)庫集群、數(shù)據(jù)庫和表

參考

數(shù)據(jù)庫集群的邏輯結(jié)構(gòu)

數(shù)據(jù)庫集群是由 PostgreSQL 服務(wù)器管理 的數(shù)據(jù)庫集合。 PostgreSQL 中的術(shù)語“數(shù)據(jù)庫集群”并不意味著“一組數(shù)據(jù)庫服務(wù)器”。PostgreSQL 服務(wù)器在單個主機上運行并管理單個數(shù)據(jù)庫集群。

數(shù)據(jù)庫是數(shù)據(jù)庫對象的集合。在關(guān)系數(shù)據(jù)庫理論中,數(shù)據(jù)庫對象是一種用于存儲或引用數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。(堆)表就是它的一個典型例子,還有很多像索引、序列、視圖、函數(shù)等。在 PostgreSQL 中,數(shù)據(jù)庫本身也是數(shù)據(jù)庫對象,并且在邏輯上是相互分離的。所有其他數(shù)據(jù)庫對象(例如,表、索引等)都屬于它們各自的數(shù)據(jù)庫。

數(shù)據(jù)庫集群的邏輯結(jié)構(gòu)

PostgreSQL 中的所有數(shù)據(jù)庫對象都由各自的對象標識符 (OID)進行內(nèi)部管理,它們是無符號的 4 字節(jié)整數(shù)。根據(jù)對象的類型,數(shù)據(jù)庫對象和相應(yīng) OID 之間的關(guān)系存儲在適當?shù)南到y(tǒng)目錄中。例如,數(shù)據(jù)庫和堆表的 OID 分別存儲在pg_database和pg_class中。

openGauss=# select datname, oid from pg_database where datname='test';
 datname |  oid
---------+-------
 test    | 16386
(1 row)

數(shù)據(jù)庫集群的物理結(jié)構(gòu)

數(shù)據(jù)庫集群基本上是 一個稱為基本目錄的目錄,它包含一些子目錄和大量文件。如果您執(zhí)行initdb實用程序來初始化新的數(shù)據(jù)庫集群,則會在指定目錄下創(chuàng)建一個基本目錄。雖然不是強制性的,但基本目錄的路徑通常設(shè)置為環(huán)境變量PGDATA。

下圖顯示了 PostgreSQL 中的數(shù)據(jù)庫集群示例。數(shù)據(jù)庫是基本子目錄下的子目錄,每個表和索引都是(至少)一個存儲在其所屬數(shù)據(jù)庫的子目錄下的文件。還有幾個包含特定數(shù)據(jù)和配置文件的子目錄。雖然 PostgreSQL 支持tablespaces,但該術(shù)語的含義與其他 RDBMS 不同。PostgreSQL 中的表空間是一個包含基本目錄之外的一些數(shù)據(jù)的目錄。

數(shù)據(jù)庫集群的一個例子

數(shù)據(jù)庫集群布局

根目錄文件

文件 描述
PG_VERSION 包含 PostgreSQL 主要版本號的文件
pg_hba.conf 用于控制 PosgreSQL 客戶端身份驗證的文件
pg_ident.conf 一個控制 PostgreSQL 用戶名映射的文件
postgresql.conf 用于設(shè)置配置參數(shù)的文件
postgresql.auto.conf 用于存儲在 ALTER SYSTEM(版本 9.4 或更高版本)中設(shè)置的配置參數(shù)的文件
postmaster.opts 記錄服務(wù)器上次啟動時使用的命令行選項的文件

子目錄

子目錄 描述
base/ 包含每個數(shù)據(jù)庫子目錄的子目錄。
global/ 包含集群范圍表的子目錄,例如 pg_database 和 pg_control。
pg_commit_ts/ 包含事務(wù)提交時間戳數(shù)據(jù)的子目錄。版本 9.5 或更高版本。
pg_clog/(9.6 或更早版本) 包含事務(wù)提交狀態(tài)數(shù)據(jù)的子目錄。在版本 10 中它被重命名為pg_xact
pg_dynshmem/ 包含動態(tài)共享內(nèi)存子系統(tǒng)使用的文件的子目錄。版本 9.4 或更高版本。
pg_logical/ 包含用于邏輯解碼的狀態(tài)數(shù)據(jù)的子目錄。版本 9.4 或更高版本。
pg_multixact/ 包含多事務(wù)狀態(tài)數(shù)據(jù)的子目錄(用于共享行鎖)
pg_notify/ 包含 LISTEN/NOTIFY 狀態(tài)數(shù)據(jù)的子目錄
pg_repslot/ 包含復制槽 數(shù)據(jù)的子目錄。版本 9.4 或更高版本。
pg_serial/ 包含有關(guān)提交的可序列化事務(wù)信息的子目錄(9.1 或更高版本)
pg_snapshots/ 包含導出快照的子目錄(版本 9.2 或更高版本)。PostgreSQL 的函數(shù) pg_export_snapshot 在這個子目錄中創(chuàng)建一個快照信息文件。
pg_stat/ 包含統(tǒng)計子系統(tǒng)的永久文件的子目錄。
pg_stat_tmp/ 包含統(tǒng)計子系統(tǒng)的臨時文件的子目錄。
pg_subtrans/ 包含子事務(wù)狀態(tài)數(shù)據(jù)的子目錄
pg_tblspc/ 包含指向表空間的符號鏈接的子目錄
pg_twophase/ 包含準備交易的狀態(tài)文件的子目錄
pg_wal/(版本 10 或更高版本) 包含 WAL(預(yù)寫日志記錄)段文件的子目錄。它是從版本 10 中的pg_xlog重命名的。
pg_xact/(版本 10 或更高版本) 包含事務(wù)提交狀態(tài)數(shù)據(jù)的子目錄。它是從版本 10 中的 pg_clog 重命名的。
pg_xlog/(9.6 或更早版本) 包含 WAL(預(yù)寫日志記錄)段文件的子目錄。在版本 10 中它被重命名為pg_wal 。

數(shù)據(jù)庫布局

數(shù)據(jù)庫是base子目錄下的子目錄;并且數(shù)據(jù)庫目錄名稱與各自的 OID 相同。

與表和索引相關(guān)的文件布局

每個大小小于 1GB 的表或索引都是存儲在其所屬數(shù)據(jù)庫目錄下的單個文件。作為數(shù)據(jù)庫對象的表和索引在內(nèi)部由各個 OID 管理,而這些數(shù)據(jù)文件由變量relfilenode管理。表和索引的 relfilenode 值基本但并不總是與各自的 OID 匹配.

test=# SELECT relname, oid, relfilenode FROM pg_class WHERE relname = 'students';
 relname  |  oid  | relfilenode
----------+-------+-------------
 students | 16393 |       16393
(1 row)

對應(yīng)目錄:

[root@localhost base]# ll ./16386/16393
-rw------- 1 omm omm 8192 May 19 02:33 ./16386/16393

也可以使用(pg9.0以上版本,opengauss都支持):

test=# select pg_relation_filepath('students');
 pg_relation_filepath
----------------------
 base/16386/16393
  • 可以通過發(fā)出一些命令(例如,TRUNCATE、REINDEX、CLUSTER)來更改表和索引的 relfilenode 值。

  • 當表和索引的文件大小超過 1GB 時,PostgreSQL 會創(chuàng)建一個名為 relfilenode.1 的新文件并使用它。如果新文件已填滿,將創(chuàng)建下一個名為 relfilenode.2 的新文件,依此類推。

  • 仔細查看數(shù)據(jù)庫子目錄,你會發(fā)現(xiàn)每個表都有兩個關(guān)聯(lián)文件,分別以'_fsm'和'_vm'為后綴。這些被稱為空閑空間映射可見性映射,分別存儲空閑空間容量和表格文件中每個頁面的可見性信息(參見第 5.3.4節(jié)和第 6.2節(jié)中的更多詳細信息)。索引只有單獨的可用空間圖,沒有可見性圖。它們也可以在內(nèi)部稱為每個關(guān)系的分支;可用空間映射是表/索引數(shù)據(jù)文件的第一個分支(分支編號為 1),可見性映射是表數(shù)據(jù)文件的第二個分支(分支編號為 2)。數(shù)據(jù)文件的fork號為0。

表空間

PostgreSQL 中的表空間是基本目錄之外的附加數(shù)據(jù)區(qū)域。下圖顯示了一個表空間的內(nèi)部布局,以及與主數(shù)據(jù)區(qū)的關(guān)系。

數(shù)據(jù)庫集群中的一個表空間

堆表文件的內(nèi)部布局

在數(shù)據(jù)文件(堆表和索引,以及空閑空間映射和可見性映射)內(nèi)部,分為固定長度的(或塊),默認為 8192 字節(jié)(8 KB)。每個文件中的那些頁面從 0 開始依次編號,這些編號稱為塊編號。如果文件已被填滿,PostgreSQL 會在文件末尾添加一個新的空頁以增加文件大小。

堆表文件的頁面布局

表中的一個頁面包含如下描述的三種數(shù)據(jù):

  1. heap tuple(s) ——堆元組本身就是一個記錄數(shù)據(jù)。它們從頁面底部開始按順序堆疊。tuple 的內(nèi)部結(jié)構(gòu)此處暫不討論。

  2. line pointer(s) – 一個行指針有 4 個字節(jié)長,并保存一個指向每個堆元組的指針。它也稱為item pointer
    行指針組成一個簡單的數(shù)組,起到元組索引的作用。每個索引從 1 開始按順序編號,稱為偏移編號。當一個新的元組被添加到頁面時,一個新的行指針也被推到數(shù)組上以指向新的。

  3. 標頭數(shù)據(jù)——由結(jié)構(gòu)[PageHeaderData](javascript:void(0))定義的標頭數(shù)據(jù)分配在頁面的開頭。它長 24 字節(jié),包含有關(guān)頁面的一般信息。結(jié)構(gòu)的主要變量如下所述。

    • pd_lsn——這個變量存儲了本頁最后一次更改寫入的 XLOG 記錄的 LSN。它是一個 8 字節(jié)的無符號整數(shù),與 WAL(Write-Ahead Logging)機制有關(guān)。
    • pd_checksum – 此變量存儲此頁面的校驗和值。(注意9.3及以后版本支持這個變量;在早期版本中,這部分已經(jīng)存儲了頁面的timelineId。)
    • pd_lower, pd_upper – pd_lower 指向行尾指針,pd_upper 指向最新堆元組的開頭。
    • pd_special – 此變量用于索引。在表中的頁面中,它指向頁面的末尾。(在索引內(nèi)的頁面中,它指向特殊空間的開頭,這是僅由索引持有的數(shù)據(jù)區(qū)域,根據(jù)索引類型的種類,如B-tree、GiST、GiN等包含特定的數(shù)據(jù)。)

行尾指針和最新元組開頭之間的空白空間稱為空閑空間空洞。

為了識別表中的元組,內(nèi)部使用了元組標識符 (TID)。TID 包含一對值:包含元組的頁面的塊號,以及指向元組的行指針的偏移量。其用法的一個典型例子是索引。

元組的讀寫方法

編寫堆元組

假設(shè)一個表由一頁組成,其中只包含一個堆元組。該頁的 pd_lower 指向第一行指針,行指針和 pd_upper 都指向第一個堆元組。見圖 1.5(a)。

當?shù)诙€元組被插入時,它被放在第一個元組之后。第二行指針被推到第一個上,它指向第二個元組。pd_lower 更改為指向第二行指針,pd_upper 更改為指向第二個堆元組。見圖 1.5(b)。此頁面中的其他標題數(shù)據(jù)(例如,pd_lsn、pg_checksum、pg_flag)也被重寫為適當?shù)闹怠?/p>

堆元組的編寫

讀取堆元組

這里概述了兩種典型的訪問方法,順序掃描和 B-tree 索引掃描:

  • 順序掃描——通過掃描每頁中的所有行指針順序讀取所有頁中的所有元組。見圖 1.6(a)。
  • B-tree 索引掃描 ——一個索引文件包含索引元組,每個索引元組由一個索引鍵和一個指向目標堆元組的 TID 組成。如果找到了具有您要查找的鍵的索引元組,則 PostgreSQL 使用獲得的 TID 值讀取所需的堆元組。(B-tree index中查找索引元組的方法,由于很常見,篇幅有限,這里就不做說明了,見相關(guān)資料。)例如,圖1.6(b)中,TID得到的索引元組的值為'(block = 7, Offset = 2)'。這意味著目標堆元組是表內(nèi)第 7 頁中的第 2 個元組,因此 PostgreSQL 可以讀取所需的堆元組,而無需在頁面中進行不必要的掃描。
順序掃描和索引掃描
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容