PostgreSQLのデータファイルの中身を確認する
Postgresのマニュアルに、データファイルのレイアウトが載っていた。 www.postgresql.jp
テーブルに行を挿入して、実際に書き込まれるデータを確認してみる。
手順
データファイルのパスを調べる
テーブルを作成して、テーブルのファイルパスを調べる。
CREATE TABLE datafiletest (name varchar(100), age integer); SELECT pg_relation_filepath('datafiletest'); -- base/16388/24577 SHOW data_directory; -- /var/lib/postgresql/15/main
postgresのデータディレクトリからのパスが返ってくるので、データファイルは/var/lib/postgresql/15/main/base/16388/24577
にあることがわかる。
データファイルの更新を確認する
デーブルを作成した時点ではファイルは空。0バイト。
postgres@TANAKA-DESKTOP:/home/ytnk531$ ls -l /var/lib/postgresql/15/main/base/16388 /24577 -rw------- 1 postgres postgres 0 1月 5 18:17 /var/lib/postgresql/15/main/base/16388/24577
データを追加する。 この時点ではWAL(先行書き込みログ)が記録されただけで、データファイルへの反映はされないので、CHECKPOINTを使って強制的にデータファイルを更新する。
INSERT INTO datafiletest VALUES('test', 10); CHECKPOINT;
postgres@TANAKA-DESKTOP:/home/ytnk531$ ls -l /var/lib/postgresql/15/main/base/16388 /24577 -rw------- 1 postgres postgres 8192 1月 5 18:30 /var/lib/postgresql/15/main/base/16388/24577
このデータファイルには、今のところ1ページ分だけ書き込まれている。 マニュアルを頼りに読んでいく。 70.6. データベースページのレイアウト
まずヘッダ部分を確認するために、32バイトだけ読む。
postgres@TANAKA-DESKTOP:/home/ytnk531$ hexdump -C -n 32 /var/lib/postgresql/15/main /base/16388/24577 00000000 00 00 00 00 e8 85 9a 01 00 00 00 00 1c 00 d8 1f |................| 00000010 00 20 04 20 00 00 00 00 d8 9f 48 00 00 00 00 00 |. . ......H.....| 00000020
PageHeaderData 00 00 00 00 e8 85 9a 01 00 00 00 00 1c 00 d8 1f 00 20 04 20 00 00 00 00
- pd_lsn 00 00 00 00 e8 85 9a 01
- pd_checksum 00 00
- pd_flags 00 00
- pd_lower 1c 00
- pd_upper d8 1f
- pd_special 00 20
- pd_pagesize_version 04 20
- pd_prune_xid 00 00
pd_upperが、空き領域の終わりのアドレスを指す。リトルエンディアンなので、1fd8を指している。
ItemIdData
d8 9f 48 00
1アイテム分。
postgres/itemid.h at c8e1ba736b2b9e8c98d37a5b77c4ed31baf94147 · postgres/postgres · GitHub
- オフセット 11011000 0011111 -> 1f d8
- フラグ 10
- 長さ 1001000 00000000 -> 8 bytes
一つ目のレコードまでのオフセットが1fd8なので、データは1fd9から始まることがわかる。
postgres@TANAKA-DESKTOP:/home/ytnk531$ hexdump -C -s 8152 /var/lib/postgresql/15/ma in/base/16388/24577 00001fd8 eb 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00001fe8 01 00 02 00 02 09 18 00 0b 74 65 73 74 00 00 00 |.........test...| 00001ff8 0a 00 00 00 00 00 00 00 |........| 00002000
HeapTupleHeaderData eb 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 02 00 02 09 18 00
- t_xmin eb 02 00 00
- t_xmax 00 00 00 00
- t_cid 00 00 00 00
- t_xvac なし?(t_cidとt_xvacは共用体)
- t_ctid 00 00 00 00 01 00
- t_infomask2 02 00
- t_infomask 02 09
- t_hoff 18
hoffが18なので実際のデータは1ff1から始まる。
postgres@TANAKA-DESKTOP:/home/ytnk531$ hexdump -C -s 8177 /var/lib/postgresql/15/ma in/base/16388/24577 00001ff1 74 65 73 74 00 00 00 0a 00 00 00 00 00 00 00 |test...........|
- name 74 65 73 74 -> test
- age 00 00 00 0a -> 100
なんやかんや読み取れた。 後ろの4バイトは何なのかわからない。
nameを長くすると、いい感じに後ろに詰まる。4バイトごとにalignされている。
postgres@TANAKA-DESKTOP:/home/ytnk531$ hexdump -C -s 8177 /var/lib/postgresql/15/main/base/16388/24588 00001ff1 74 65 73 74 65 64 62 65 00 00 00 0a 00 00 00 |testedbe.......| 00002000