疑問
前幾天PG學習微信群有人在問“pg_class 存儲了對象和命名空間,表空間的對應關系,為什么沒有和數據庫的關系?我想查數據庫下面有多少對象,找不到數據庫和對象的關系?”
簡而言之;PostgreSQL數據庫和對象的關系;提這個問題的同學;應該是想知道
PostgreSQL實例中數據庫之間的關系,以及數據庫和對象的關系。
至於能否有這樣的SQL;容我一步一步探索
探索
1、探索PG的邏輯結構
邏輯結構圖
上圖解析:
- 第一層是實例(Instance)。
- 第二層是數據庫(Database);一個實例下有多個數據庫;每個數據庫之間是完全獨立的。
- 第三層是Schema;數據庫下面有多個Schema;其中“public” 是數據庫創建時產生的。
- 每個Schema下面可以創建表,視圖,索引,函數,序列,物化視圖,外部表等等。
由於在PostgreSQL每個數據庫是完全獨立的;這可以解釋另外一個問題(為什么訪問同一個實例下其他數據庫為什么要借用 dblink或者fdw接口?)。
這時可能會有學MYSQL同學會問到;(為什么在MYSQL中可以訪問同實例下其他數據庫?)。其實MYSQL跟PostgreSQL邏輯結構不一樣;其中MYSQL實例中的數據庫相當於PostgreSQL上圖的第三層的Schema。
2、探索PG數據庫中schema
了解過PostgreSQL的同學都知道;我們通過系統表pg_database可以查到數據庫,通過系統表pg_class可以查到數據庫object。
postgres=# select datname, oid from pg_database where datname = 'postgres';
datname | oid
----------+-------
postgres | 13543
(1 row)
postgres=# select relname, oid from pg_class where oid = 't1' :: regclass;
relname | oid
---------+-------
t1 | 32768
(1 row)
而pg_database、pg_class存放在一個名為pg_catalog的Schema下。其中pg_catalog是系統級的schema,用於存儲系統函數和系統元數據、而每個 database 創建好后,默認會有3個Schema。
-
一個名為pg_catalog,用於存儲Postgresql系統自帶的函數,表,系統視圖,數據類型轉換器以及數據類型定義等元數據
-
一個名為information_schema,用於存儲所需求提供的元數據查詢視圖,目的是以符合ANSI SQL規范,可單獨刪除
-
一個名為public,用於存儲用戶創建的數據表。不建議項目的表存放在public下,1、是數據安全;2、表存放混亂;不利於后期維護等等
查看schema
-- 通過元命令查看
lottu=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
-- 查看隱藏的schema
lottu=# select table_schema
lottu-# from information_schema.tables
lottu-# group by table_schema;
table_schema
--------------------
information_schema
pg_catalog
(2 rows)
-- 系統表存放的schema是在pg_catalog下;
lottu=# \d pg_catalog.pg_class
lottu=# \d pg_catalog.pg_database
--這里我們先拋出一個問題;后面解析;每個數據庫的pg_class是同一個嗎?
3、探索PG數據庫中catalog
我們知道新建一個數據庫會在表空間對應的目錄下創建一個 oid(數據庫oid)的目錄;用於存放這個數據庫對應的數據庫文件。
-- 例如數據庫lottu
lottu=# select oid, datname from pg_database where datname='lottu';
oid | datname
-------+---------
32771 | lottu
(1 row)
--對應的目錄就會有一個32771的文件夾
[postgres@node3 ~]$ ll /data/postgres/data/base/
total 32
drwx------. 2 postgres postgres 4096 Sep 16 10:54 1
drwx------. 2 postgres postgres 4096 Sep 16 10:54 13542
drwx------. 2 postgres postgres 12288 Sep 21 11:44 13543
drwx------. 2 postgres postgres 12288 Sep 21 14:33 32771
-- 在 數據庫lottu中;其中的table_catalog
lottu=# select table_catalog
lottu-# from information_schema.tables
lottu-# group by table_catalog;
table_catalog
---------------
lottu
(1 row)
-- 在數據庫 postgres中;其中table_catalog是postgres。
lottu=# \c postgres
You are now connected to database "postgres" as user "postgres".
postgres=# select table_catalog
from information_schema.tables
group by table_catalog;
table_catalog
---------------
postgres
(1 row)
通過上述實驗;我們可以了解到PG同實例下數據庫之間不僅物理結構完全獨立,邏輯結構也是完全獨立。這個不僅作用於用戶表,還作用於系統表。現在來解析上面拋出的問題“每個數據庫的pg_class是同一個嗎”?
-- 在postgres數據庫中
postgres=# select table_catalog, table_schema, table_name, table_name :: regclass ::oid from information_schema.tables where table_name = 'pg_class';
table_catalog | table_schema | table_name | table_name
---------------+--------------+------------+------------
postgres | pg_catalog | pg_class | 1259
(1 row)
--在 lottu 數據庫中
lottu=# select table_catalog, table_schema, table_name, table_name :: regclass ::oid from information_schema.tables where table_name = 'pg_class';
table_catalog | table_schema | table_name | table_name
---------------+--------------+------------+------------
lottu | pg_catalog | pg_class | 1259
(1 row)
--根據oid找到文件
[postgres@node3 data]$ find . -name '1259*'
./base/1/1259
./base/1/1259_vm
./base/1/1259_fsm
./base/13543/1259
./base/13543/1259_vm
./base/13543/1259_fsm
./base/13542/1259
./base/13542/1259_vm
./base/13542/1259_fsm
./base/32771/1259
./base/32771/1259_vm
./base/32771/1259_fsm
結果:
- 在邏輯結構上;同實例下每個數據庫的表是在存放在同庫名的catalog下。
- 在物理結構上;同實例下每個數據庫的pg_class對應的數據文件也是獨立存放的。
結論
- 在PG中;同實例下每個數據庫是完全獨立;表是在存放在同庫名的catalog下;例如Postgres數據庫的表存放在Postgres的catalog下,可以把catalog理解為database。同時物理結構是也是獨立存放的
- 每個 database 創建時;會默認為庫創建pg_catalog/information_schema
最后,前面的疑問“PostgreSQL實例中數據庫之間的關系,以及數據庫和對象的關系”,應該很好解釋清楚。
參考文獻
https://www.postgresql.org/docs/current/catalogs.html
https://www.postgresql.org/docs/current/infoschema-schema.html