oracle中有個特性:deferred segment createion。那么在postgresql中,在創建表或者索引的時候,磁盤上對應的文件是立即創建還是插入第一行數據的時候創建呢?
postgres=# create table t1(a int); CREATE TABLE postgres=# select pg_relation_filepath('t1'); pg_relation_filepath ---------------------- base/13878/75000 (1 row) postgres=# \! oid2name -d postgres -t t1 From database "postgres": Filenode Table Name ---------------------- 75000 t1 postgres=#
現在我們看看文件是否已經被創建
$ ls -la $PGDATA/base/13878/75000 -rw------- 1 postgres postgres 0 Oct 31 19:18 /pg/11/data/base/13878/75000
文件已經被創建,但是是空文件。
但是還沒有創建visibility map和free space map文件:
$ ls -la $PGDATA/base/13878/75000* -rw------- 1 postgres postgres 0 Oct 31 19:18 /pg/11/data/base/13878/75000
如果我們在這個空表上創建一個索引會發生什么呢?
postgres=# create index i1 on t1 (a); CREATE INDEX postgres=# select pg_relation_filepath('i1'); pg_relation_filepath ---------------------- base/13878/75003 (1 row) postgres=# \! ls -la $PGDATA/base/13878/75003 -rw------- 1 postgres postgres 8192 Oct 31 19:27 /pg/11/data/base/13878/75003
索引文件立即被創建了,但是不是一個空文件。恰好是一個page的大小。使用pageinspect我們可以確定這個頁只是存放了元數據。
postgres=# create extension pageinspect; CREATE EXTENSION postgres=# SELECT * FROM bt_metap('i1'); magic | version | root | level | fastroot | fastlevel | oldest_xact | last_cleanup_num_tuples --------+---------+------+-------+----------+-----------+-------------+------------------------- 340322 | 3 | 0 | 0 | 0 | 0 | 0 | -1 (1 row) postgres=# SELECT * FROM bt_page_stats('i1', 0); ERROR: block 0 is a meta page postgres=#
到此為止,還有一個問題,free space map和visibility map文件是什么時候創建的呢?是在第一個插入之后?
postgres=# insert into t1 (a) values (1); INSERT 0 1 postgres=# \! ls -la $PGDATA/base/13878/75000* -rw------- 1 postgres postgres 8192 Oct 31 19:33 /pg/11/data/base/13878/75000 postgres=#
顯然不是。正確的答案是在vacuum之后。
postgres=# vacuum t1; VACUUM postgres=# \! ls -la $PGDATA/base/13878/75000* -rw------- 1 postgres postgres 8192 Oct 31 19:33 /pg/11/data/base/13878/75000 -rw------- 1 postgres postgres 24576 Oct 31 19:34 /pg/11/data/base/13878/75000_fsm -rw------- 1 postgres postgres 8192 Oct 31 19:34 /pg/11/data/base/13878/75000_vm postgres=#