[PostgreSQL] pg_hexeditを使ってファイル構造を確認する

#はじめに
PostgreSQL Advent Calendarに乗り遅れた！（挨拶）
PostgreSQLのデータファイルをバイナリエディタで確認するユーティリティを使ってみたので、そのメモです。
ソースや使い方は以下から。
https://github.com/petergeoghegan/pg_hexedit

インストールの仕方は上記サイトに載ってるので割愛。
データが壊れるかもしれないのでローカルの開発環境で利用してね、ってことらしいです。

#検証
早速テスト用テーブルを作って試してみます。

```SQL
create table hoge (col1 varchar, col2 varchar);
insert into hoge values ('00001','AAAAA');
```
実行はrelation_hexedit シェルの引数にテーブル名を指定する形です。

```bash
matsu@matsu-TM1613:~/pg_hexedit$ ./relation_hexedit hoge
```

導入が成功していると以下のようなウィンドウが起動します。

![wxHexEditor 0.24 Beta Development for Linux_001.png](https://qiita-image-store.s3.amazonaws.com/0/219961/f006234a-5e35-5f0b-6bc2-2fd6457e65b9.png)

INSERTしたデータはファイルの末尾の方にあります。

![wxHexEditor 0.24 Beta Development for Linux_002.png](https://qiita-image-store.s3.amazonaws.com/0/219961/808c973a-b12e-2da5-d61f-6bcd0243ff73.png)

00000やAAAAAがウィンドウの右側に表示されているのがわかります。
PostgreSQLはブロックの後ろの方からデータを書いていくので、先程INSERTしたデータはこの時点でファイルの末尾にあります。
ちなみにPostgreSQLのファイル構造についてはsrc/include/storage/bufpage.h のコメントに説明があります。

```
 22 /*
 23  * A postgres disk page is an abstraction layered on top of a postgres
 24  * disk block (which is simply a unit of i/o, see block.h).
 25  *
 26  * specifically, while a disk block can be unformatted, a postgres
 27  * disk page is always a slotted page of the form:
 28  *
 29  * +----------------+---------------------------------+
 30  * | PageHeaderData | linp1 linp2 linp3 ...           |
 31  * +-----------+----+---------------------------------+
 32  * | ... linpN |                                      |
 33  * +-----------+--------------------------------------+
 34  * |           ^ pd_lower                             |
 35  * |                                                  |
 36  * |             v pd_upper                           |
 37  * +-------------+------------------------------------+
 38  * |             | tupleN ...                         |
 39  * +-------------+------------------+-----------------+
 40  * |       ... tuple3 tuple2 tuple1 | "special space" |
 41  * +--------------------------------+-----------------+
 42  *                                  ^ pd_special
 43  *
```
1枚めの画像ではPageHeaderDataとlinp1、2枚めの画像ではtuple1に相当する部分が表示されてます。
末尾のspecial spaceの領域は無いようです。（ヘッダのpd_specialで指してるアドレスが8192）

もうちょっとデータをINSERTして、UPDATEしてみます。

```SQL
insert into hoge values ('00002','BBBBB');
insert into hoge values ('00003','CCCCC');
update hoge set col2='CCCCC' where col1='00002';
```
![wxHexEditor 0.24 Beta Development for Linux_003.png](https://qiita-image-store.s3.amazonaws.com/0/219961/d55f5842-f758-3dc2-07f4-62d5e6a408ba.png)

後ろの方からレコードが追加されていることがわかります。
また、UPDATEしたデータに着目すると、UPDATE前のレコード（00002とBBBBBのレコード）が8137、UPDATE後のレコード（00002とCCCCCのレコード）が8056のあたりにあることがわかります。PostgreSQLは追記型アーキテクチャである、ということが目視できて少し感動です。
UPDATEの次はvacuumしてみますか

```SQL
vacuum hoge;
```
![wxHexEditor 0.24 Beta Development for Linux_005.png](https://qiita-image-store.s3.amazonaws.com/0/219961/4d062294-9ce8-b87e-de91-469e745fc766.png)

8032〜8071のデータはデータが上書きされていませんが、ツール上色付けされてないです。おそらくここが開放された領域と考えられます。この状態で、INSERTするとこの領域が上書きされることが期待されます。

```SQL
insert into hoge values ('00004','DDDDD');
```

![wxHexEditor 0.24 Beta Development for Linux_007.png](https://qiita-image-store.s3.amazonaws.com/0/219961/d0bb98c5-bc1a-43e6-615b-4b33069276c9.png)

期待通り、開放された領域が別レコードで上書きされています。

#まとめ
というわけで、このpg_hexeditを使うとUPDATEやVACUUM実行時のファイル構造が簡単に見られて良さげでした。
本当はツール上で対象データのところにマウスポインタを置くと、データ型とかが表示されるのでもっとわかりやすいです（単にスクショとるときの都合でここでは表示できてないです。。）

↓のページの内容やソースコードと照らし合わせながら確認すると理解が進みそうなので、今後チャレンジしていきたいところです。
http://pgsqldeepdive.blogspot.jp/2012/12/postgresql_16.html