Visibility Mapの中身を見る

序章
======
PostgreSQLのテーブルにはテーブルごとにVisibility Mapが存在していて、VACUUM処理を高速化したり、Index Only Scanの際に用いられます。
Visibility Mapについての詳細は[公式マニュアル](http://www.postgresql.jp/document/9.4/html/storage-vm.html)をご参照ください。

**VMの高速化についての詳細は公式マニュアルには書いてない**のですが、Visibility Mapを使ってVACUUMをスキップするのは、**Visibility Mapのビット列で、1（つまりall-visible）が連続で32個以上続いた時のみ**になります。これはOSの先読み機能によりVACUUM対象よりの先のページをすでに読み込んでいる為、ゴミのあるページがある程度まとまっている状態でスキップしないと逆に性能が悪くなってしまう為、このような仕様になっています。

テーブルのページ数や、その中でall-visibleであるページの数はpg_class.relallvisibleにて確認することができるのですが、上記の理由により同じrelallvisibleの値でもVACUUMの実行時間は異なりますし、Visibility Mapがどのような状況になっているかは、現在のPostgreSQLではPostgreSQLから見ることは出来ません。(9.5で出来ません）

そこで、本ページではVisibility Mapの中身の見方といくつかのVisibility Mapの状態を紹介します。

Visibility Map(VM)の見方
========================

Visibility Mapは<relfilenode>_vmというファイルになっているので、そのファイルをxxdコマンド等で見るだけです。

# 1. すべてall-visibleなVisibility Map
VACUUM時全ページスキップするので一瞬で終わる
※ページヘッダが24Byteなので、上から４行はページヘッダです。

```:
 relname | relfilenode | relpages | relallvisible
---------+-------------+----------+---------------
 hoge    |       41018 |      443 |           443
(1 row)

$ xxd -b data/base/13247/41018_vm | head -15
0000000: 00000000 00000000 00000000 00000000 10101000 10000111  ......
0000006: 01100100 00011000 00000000 00000000 00000000 00000000  d.....
000000c: 00011000 00000000 00000000 00100000 00000000 00100000  ... .
0000012: 00000100 00100000 00000000 00000000 00000000 00000000  . ....
0000018: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000001e: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000024: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000002a: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000030: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000036: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000003c: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000042: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000048: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000004e: 11111111 00000111 00000000 00000000 00000000 00000000  ......
```

#2. ゴミがある箇所がまとまっているVisibilityMap
最初の部分と最後の部分でVACUUMをスキップできるので高速にVACUUMをができる
※ページヘッダが24Byteなので、上から４行はページヘッダです。

```:
 relname | relfilenode | relpages | relallvisible
---------+-------------+----------+---------------
 hoge    |       41020 |      443 |           221
(1 row)

$ xxd -b data/base/13247/41020_vm | head -15
0000000: 00000000 00000000 00000000 00000000 10010000 11001010  ......
0000006: 00101010 00011001 00000000 00000000 00000000 00000000  *.....
000000c: 00011000 00000000 00000000 00100000 00000000 00100000  ... .
0000012: 00000100 00100000 00000000 00000000 00000000 00000000  . ....
0000018: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000001e: 11111111 11111111 11111111 11111111 11111111 11111111  ......
0000024: 11111111 11111111 11111111 11111111 00001111 00000000  ......
000002a: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000030: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000036: 00000000 00000000 00000000 00000000 00000000 00000000  ......
000003c: 00000000 00000000 00000000 00000000 00000000 00000000  ......
0000042: 00000000 00000000 11111100 11111111 11111111 11111111  ......
0000048: 11111111 11111111 11111111 11111111 11111111 11111111  ......
000004e: 11111111 00000111 00000000 00000000 00000000 00000000  ......
```

# 3. ゴミの箇所がまばらにあるVisibility Map
32個以上まとまった「1」がないため、VACUUM時はテーブルをフルスキャンになり、非常に遅いVACUUMになる。
※ページヘッダが24Byteなので、上から４行はページヘッダです。

```:
 relname | relfilenode | relpages | relallvisible
---------+-------------+----------+---------------
 hoge    |       41019 |      443 |           221
(1 row)

$ xxd -b data/base/13247/41019_vm | head -15
0000000: 00000000 00000000 00000000 00000000 11101000 10100001  ......
0000006: 11000111 00011000 00000000 00000000 00000000 00000000  ......
000000c: 00011000 00000000 00000000 00100000 00000000 00100000  ... .
0000012: 00000100 00100000 00000000 00000000 00000000 00000000  . ....
0000018: 10101010 10101010 10101010 10101010 10101010 10101010  ......
000001e: 10101010 10101010 10101010 10101010 10101010 10101010  ......
0000024: 10101010 10101010 10101010 10101010 10101010 10101010  ......
000002a: 10101010 10101010 10101010 10101010 10101010 10101010  ......
0000030: 10101010 10101010 10101010 10101010 10101010 10101010  ......
0000036: 10101010 10101010 10101010 10101010 10101010 10101010  ......
000003c: 10101010 10101010 10101010 10101010 10101010 10101010  ......
0000042: 10101010 10101010 10101010 10101010 10101010 10101010  ......
0000048: 10101010 10101010 10101010 10101010 10101010 10101010  ......
000004e: 10101010 00000010 00000000 00000000 00000000 00000000  ......
```

2と3はrelallvisibleの数が同じなのに、VACUUMの速度は3の方が遅くなります。