PostgreSQL:物理結構

Ryan_Bai發表於2020-09-03

在執行 initdb 的時候會初始化一個目錄,通常我們都會在系統配置相關的環境變數 $PGDATA 來表示,初始化完成後,會在這個目錄生成相關的子目錄以及一些檔案。在 postgresql 中,tablespace 的概念並不同於其他關係型資料庫,這裡一個 tablespace 對應的都是一個目錄。如下圖就是 PG 的物理結構。

檔案和目錄相關作用描述

files description
PG_VERSION 包含 postgresql 主版本號的檔案
pg_hba.conf 控制 postgresql 客戶端驗證的檔案
pg_ident.conf 控制 postgresql 使用者名稱對映的檔案<br/>配置作業系統使用者和資料庫伺服器上的使用者名稱的對映
postgresql.conf 配置引數檔案
postgresql.auto.conf 用於儲存在 ALTER SYSTEM(版本9.4或更高版本)中設定的配置引數的檔案
postmaster.opts 記錄伺服器最後一次啟動時使用的命令列引數
postmaster.pid 伴隨資料庫伺服器一同啟動,記錄資料庫伺服器程式編號、PGDATA、埠等資訊的檔案
subdirectories description
base/ 包含每個資料庫子目錄的子目錄
global/ 包含群集範圍的表的子目錄,例如 pg_database、pg_control
pg_commit_ts/ (Version 9.5 or later) 包含事務提交時間戳資料的子目錄。
pg_clog/ (Version 9.6 or earlier) \| pg_xact/ (Version 10 or later) 包含事務提交狀態資料的子目錄。
pg_dynshmem/ (Version 9.4 or later) 包含動態共享記憶體子系統使用的檔案的子目錄。
pg_logical/ (Version 9.4 or later) 包含邏輯複製的狀態資料的子目錄。
pg_multixact/ 包含多事務狀態資料的子目錄(用於 shared row locks)
pg_notify/ 包含 LISTEN / NOTIFY 狀態資料的子目錄
pg_repslot/ (Version 9.4 or later) 包含複製槽資料的子目錄
pg_serial/ (Version 9.1 or later) 包含已提交的可序列化事務資訊的子目錄
pg_snapshots/ (Version 9.2 or later) 包含匯出的快照的子目錄。 PostgreSQL 的 函式 pg_export_snapshot 在此子目錄中建立快照資訊檔案
pg_stat/ 包含用於統計子系統永久檔案的子目錄
pg_stat_tmp/ 包含用於統計子系統臨時檔案的子目錄
pg_subtrans/ 包含子事物狀態資料的子目錄
pg_tblspc/ 包含指向表空間的符號連結的子目錄
pg_twophase/ 包含 prepare 事務狀態檔案的子目錄
pg_xlog/ (Version 9.6 or earlier) \ | pg_wal/ (Version 10 or later) 包含預寫日誌

database 的物理佈局設計

每個資料庫都會在 $PGDATA/base 下面生成一個子目錄,如下圖,都會一一對應。

[postgres@node1 base]$ pwd
/data/pg_data/base
[postgres@node1 base]$ ll
total 36
drwx------ 2 postgres postgres 8192 Apr 30 06:29 1(template 資料庫)
drwx------ 2 postgres postgres 8192 Apr 30 06:29 13592
drwx------ 2 postgres postgres 8192 Apr 30 06:29 13593
# 其它:16384 開始
 
[postgres@node1 pg_data]$ psql -U postgres -d postgres
psql: error: could not connect to server: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
[postgres@node1 pg_data]$ pg_ctl -D /data/pg_data/ start -l /tmp/logfile
waiting for server to start.... done
server started
[postgres@node1 pg_data]$ psql -U postgres -d postgres
psql (12.2)
Type "help" for help.
 
postgres=# select datname,oid from pg_database;
  datname  |  oid  
-----------+-------
 postgres  | 13593
 template1 |     1
 template0 | 13592
(3 rows)
 
postgres=#
  • OID:所有資料庫物件都由各自的物件識別符號(OID)進行內部管理,它們是無符號的 4 位元組整數。資料庫的 OID 儲存在 pg_database 系統表中,可以透過如下程式碼查詢資料庫的 OID:

    SELECT oid, database
      FROM pg_database
     WHERE datname = 'mydb'
  • 表空間:在 PostgreSQL 中最大的邏輯儲存單位是表空間。初始化資料庫目錄時會自動建立 pg_default 和 pg_global 兩個表空間。

    postgres=# \d
            List of relations
     Schema | Name | Type  |  Owner   
    --------+------+-------+----------
     public | a    | table | postgres
    (1 row)
    • pg_global:物理檔案位置在資料目錄的 global 目錄中,它用來儲存系統表。

    • pg_default:物理檔案位置在資料目錄中的 base 目錄中,是 template0 和 template1 資料庫的預設表空間。

表和索引的物理佈局設計

每個表和索引如果不超過 1G 大小,都用一個檔案儲存,新建立的表檔案以表的OID命名,對於超出的檔案,會自動將其切分為多個檔案,用 OID.\<順序號\> 來命名。另外還有一個 relfilenode,這個值不會總是匹配 OID,在發生 truncate、reindex、cluster 等相關的操作時,會發生變化。見如下示例:

可以看到開始 oid 和 relfilenode 是一樣的,truncate 後,relfilenode 發生了變化.

postgres=# create table a(id int);
CREATE TABLE
postgres=# SELECT relname, oid, relfilenode FROM pg_class WHERE relname = 'a';
 relname |  oid  | relfilenode 
---------+-------+-------------
 a       | 16385 |       16385
(1 row)
 
postgres=# truncate table a;
TRUNCATE TABLE
postgres=# SELECT relname, oid, relfilenode FROM pg_class WHERE relname = 'a';
 relname |  oid  | relfilenode 
---------+-------+-------------
 a       | 16385 |       16388
(1 row)
 
postgres=# SELECT pg_relation_filepath('a');
 pg_relation_filepath 
----------------------
 base/14187/16388
(1 row)
 
postgres=#

如果資料資料檔案超過1GB,那麼就會新生成一個檔案,如下:

$ ls -la -h base/14187/16388*
-rw------- 1 postgres postgres 1.0G  Apr  21 11:16 base/14187/16388
-rw------- 1 postgres postgres  45M  Apr  21 11:20 base/14187/16388.1

注意:表和索引的檔案大小的限制可以在編譯的時候透過--with-segsize設定

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31490526/viewspace-2716802/,如需轉載,請註明出處,否則將追究法律責任。

相關文章