20140531 JPUGしくみ+アプリケーション分科会 勉強会資料
-
Upload
kasaharatt -
Category
Technology
-
view
1.091 -
download
3
description
Transcript of 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料
PostgreSQLのデータ構造と内容を知る- 便利な外部ツールの一部紹介 -
JPUGしくみ + アプリーケーション分科会 勉強会2014.5.31
笠原辰仁@kasa_zip
アジェンダ● はじめに● PostgreSQLを構成するデータ● 構造、状況を把握するツール群● 各種ツールの使い方と代表的な利用例
はじめに● 本日は、PostgreSQLのデータ構造やその内容を
知るために有用なツールとその簡単な使い方を紹介します
● 最近はプレ勉強会や永安氏の公開しているPostgreSQL internals など、PostgreSQLの内部を深く知るための手段や機会が増えてきました– http://www.postgresqlinternals.org/index.php/
● 内部構造を知る上で、理解の手助けになれば・・● また、最近はPostgreSQLの利用シーンも増えて
おり、データ破損などの調査も必要になるケースが増えているので・・・
PostgreSQLを構成するデータ● 代表的なデータ
名称 説明 格納先テーブル テーブルデータ。デフォルトでは8kBブ
ロックの固まりで、1GBファイル1単位に分割されている。
$PGDATA/base$PGDATA/global<テーブルスペース>/<識別子>/
インデックス インデックスデータ。基本的な構成はテーブルデータと同じ。
$PGDATA/base$PGDATA/global<テーブルスペース>/<識別子>/
FSM(Free Space Map) テーブル内に存在する空き領域の場所と大まかな空きサイズをマッピングしたファイル。
テーブルと同じ
VM(Visibility Map) テーブルのブロック単位での可視マップファイル。1ブロック1bit1で管理。不要レコードがなければ1
テーブルと同じ
一時ファイル ディスクソートやハッシュ処理時に生成される一時ファイル。処理終了時に削除される。
$PGDATA/base/pgsql_tmp
PostgreSQLを構成するデータ● 代表的なデータ
名称 説明 格納先トランザクションログ DBに変更を行った処理のログ $PGDATA/pg_xlog/コミットログ 各トランザクションのコミット状況
を記録しているログ$PGDATA/pg_clog/
制御ファイル XIDなどインスタンスの重要なメタデータを記録しているファイル(pg_control 512byte 固定)
$PGDATA/global/
稼働統計情報ファイル 内部で取得されている稼働統計情報のファイル。
$PGDATA/pg_stat/$PGDATA/pg_stat_tmp/
Multixactファイル(名前適当)
共有ロック状態を記録しているファイル。
$PGDATA/pg_multixact/
Serialファイル(名前適当)
SSIトランザクションのコミット状況を記録しているファイル。
$PGDATA/pg_serial/
サブトランザクションファイル
SAVEPOINTを使用したサブトランザクションの状況を記録しているファイル。
$PGDATA/subtrans/
スナップショットファイル
pg_export_snapshot()でエクスポートしたスナップショット情報。
$PGDATA/pg_snapshots/
PostgreSQLを構成するデータ● 代表的なデータ
名称 説明 格納先PreparedTransactionファイル
2フェーズコミット用のプリペアトランザクションの状態を記録てしているファイル。
$PGDATA/pg_twophase/
Filenodeマップファイル pg_classを経由しないアクセスが実施されるシステムカタログのOIDと物理ファイルのマップファイル(pg_filenode.map 512byte 固定)
$PGDATA/global/$PGDATA/base/
relationキャッシュファイル
各種リレーションのキャッシュファイル(backendの初期化高速用)(pg_internal.init)
$PGDATA/global/$PGDATA/base/
設定ファイル PostgreSQLの設定ファイル(postgresql.conf)
$PGDATA
アクセス制御ファイル PostgreSQLのホストベースのアクセス制御ファイル(pg_hba.conf)
$PGDATA
起動コマンドファイル PostgreSQLを起動した際のコマンドを記録したファイル(postmaster.opts)
$PGDATA
便利なツール群(主に開発)● データ構造や属性の確認に便利
名称 説明 解析対象 PostgreSQL起動
pg_filedump(外部ツール)
テーブルやインデックスデータの物理イメージをダンプして可視化するツール。pagseinspectがあればほぼ不要・・
テーブルインデックス
不要
pg_xlogdump(9.3からcontrib)
トランザクションログの内容を可視化するツール。
トランザクションログ
不要
pageinspect(8.3からcontrib)
テーブルやインデックス、FSMのメタ情報(主にヘッダ情報)を可視化するツール
テーブルインデックスFSM
必要
便利なツール群(主に検証・運用)● データの統計的な俯瞰、確認に便利
名称 説明 解析対象 PostgreSQL起動
pgstattuplet(contrib)
テーブルやインデックスの不要領域や断片化状況を数値化するツール。
テーブルインデックス
必要
pg_buffercache(contrib)
テーブルやインデックスがPostgreSQLの共有バッファにどれだけ格納されているかを数値化するツール。
テーブルインデックス
必要
pg_fincore(外部ツール)
テーブルやインデックスがOSのファイルキャッシュにどれだけ格納されているかを数値化するツール。
テーブルインデックス
必要
pg_freespacemap(contirb)
FSMにマッピングされている空き領域状況を数値化するツール。
FSM 必要
テーブル/インデックスのページ構造を調べる
* +-----------------------+---------------------------------+ * | PageHeaderData | linp1 linp2 linp3 ... | * +---------------+------+---------------------------------+ * | ... linpN | | * +---------------+-----------------------------------------+ * | ^ pd_lower | * | | * | v pd_upper | * +-------------+-------------------------------------------+ * | | tupleN ... | * +-------------+-----------------------+-------------------+ * | ... tuple3 tuple2 tuple1 | "special space"| * +--------------------------------------+-------------------+ * ^ pd_special
●
pageinspect● contribに付属しているツール● contribモジュールのmakeないしはRPMパッ
ケージ等で導入– pageinspectを実施したいDBでCREATE
EXTENSION● テーブル、インデックス名をインップットし、
ページヘッダやタプルヘッダのメタ情報の調査に有用
● 手軽に使えておすすめ
pageinspectの出力例(テーブル)(詳細は include/storage/bufpage.h)
postgres=# SELECT * FROM page_header(get_raw_page('test', 0));-[ RECORD 1 ]--------lsn | 0/1F88F90checksum | 0flags | 0lower | 44upper | 8032special | 8192pagesize | 8192version | 4prune_xid | 1094
Flagsはページ単位の状態を表すヒント。PD_PAGE_FULL ,
PD_ALL_VISIBLEなどVersionはページレイアウトの
* Page layout version number 0 is for pre-7.3
* Releases 7.3 and 7.4 use 1. * Release 8.0 uses 2 * Release 8.1 uses 3 * Release 8.3 uses 4
pageinspectの出力例(テーブル)(詳細は include/access/htup_details.h)
postgres=# SELECT * FROM heap_page_items(get_raw_page('test', 0));-[ RECORD 1 ]---------lp | 1lp_off | 8160lp_flags | 1lp_len | 28t_xmin | 1097t_xmax | 0t_field3 | 0t_ctid | (0,1)t_infomask2 | 3t_infomask | 2049t_hoff | 24t_bits | 10000000t_oid |
lp_flags はラインポインタの状態0:未使用、1:通常、
2:REDIRECT, 3: DEADt_infomaskがタプルの状態を細かく管理している重要なフラグ部位。左記は10進数
t_bitsはNULL値の管理
pageinspectの出力例(インデックス)(詳細は include/access/nbtree.h)
postgres=# SELECT * FROM bt_metap('test_pkey');-[ RECORD 1 ]-----magic | 340322version | 2root | 1level | 0fastroot | 1fastlevel | 0
pageinspectの出力例(インデックス)(詳細は include/access/nbtree.h)
postgres=# SELECT * FROM bt_page_stats('test_pkey', 1);-[ RECORD 1 ]-+-----blkno | 1type | llive_items | 3dead_items | 0avg_item_size | 16page_size | 8192free_size | 8088btpo_prev | 0btpo_next | 0btpo | 0btpo_flags | 3
btpo_* はspecial領域にあるBtree専用の情報
pageinspectの出力例(インデックス)postgres=# SELECT * FROM bt_page_items('test_pkey', 1);-[ RECORD 1 ]-----------------------Itemoffset | 1ctid | (0,1)itemlen | 16nulls | fvars | fdata | 01 00 00 00 00 00 00 00
-[ RECORD 2 ]-----------------------itemoffset | 2ctid | (0,2)itemlen | 16nulls | fvars | fdata | 02 00 00 00 00 00 00 00
ctidはテーブルのラインポインタ
data は実際のキー値
pageinspectの出力例(インデックス)postgres=# SELECT * FROM bt_page_items('test2_idx', 1);-[ RECORD 1 ]-----------------------Itemoffset | 1ctid | (0,1)itemlen | 16nulls | fvars | tdata | 01 00 00 00 09 41 41 41
-[ RECORD 2 ]-----------------------itemoffset | 2ctid | (0,2)itemlen | 16nulls | fvars | tdata | 02 00 00 00 09 42 42 42
マルチカラムインデックスはこんな感じに見える
1, 'AAA'2, 'BBB'
の16進数表記(文字の前の09はヘッダ含むサイズ)
9 >> 1 = 4 = (1 + 3)
pg_filedump● Pgfoundryで公開されている外部ツール● contribモジュール同様の手順でmake &&
make installして利用可能– PostgreSQLのバージョン毎にコードがある– PostgreSQL 9.3用はHEADを使う
● テーブル、インデックスのファイルをインップットし、ページヘッダやタプルヘッダのメタ情報の調査に有用
pg_filedumpの出力例(テーブル)pg_filedump -i /Users/postgres/base/pgsql934/base/12297/16486
Block 0 ********************************************************<Header> ----- Block Offset: 0x00000000 Offsets: Lower 40 (0x0028) Block: Size 8192 Version 4 Upper 8064 (0x1f80) LSN: logid 0 recoff 0x01f88dc8 Special 8192 (0x2000) Items: 4 Free Space: 8024 Checksum: 0x0000 Prune XID: 0x00000446 Flags: 0x0000 () Length (including item array): 40
<Data> ------ Item 1 -- Length: 32 Offset: 8160 (0x1fe0) Flags: NORMAL XMIN: 1091 XMAX: 0 CID|XVAC: 0 Block Id: 0 linp Index: 1 Attributes: 2 Size: 24 infomask: 0x0802 (HASVARWIDTH|XMAX_INVALID)
pg_filedumpの出力例(インデックス)Block 1 ********************************************************<Header> ----- Block Offset: 0x00002000 Offsets: Lower 40 (0x0028) Block: Size 8192 Version 4 Upper 8112 (0x1fb0) LSN: logid 0 recoff 0x01f89058 Special 8176 (0x1ff0) Items: 4 Free Space: 8072 Checksum: 0x0000 Prune XID: 0x00000000 Flags: 0x0000 () Length (including item array): 40
<Data> ------ Item 1 -- Length: 16 Offset: 8160 (0x1fe0) Flags: NORMAL Block Id: 0 linp Index: 1 Size: 16 Has Nulls: 0 Has Varwidths: 0
<Special Section> ----- BTree Index Section: Flags: 0x0043 (LEAF|ROOT|HASGARBAGE) Blocks: Previous (0) Next (0) Level (0) CycleId (0)
pageinspect vs pg_filedump● どちらも大体同じ情報が取れるが、pageinspect
に分がある感じ● pageinspectの良さ
– SQLで集計や検索が容易– テーブルやインデックス名で情報をひける
● pg_filedumpの良さ– PostgreSQLが停止してても使える– infomask等を分かりやすく表示する– インデックスのFlagの状態が分かる
● ただ、pg_filedumpはメンテが止まる可能性が・・– 9.3も正式版?が出ていない・・
pg_xlogdump● contribに付属しているツール● contribモジュールのmakeないしはRPMパッ
ケージ等で導入● コマンドライン● WALファイルをインップットし、トランザク
ションレコードの調査が可能● おそらくWALの内部情報を分かりやすくダンプ
する唯一のツール
pg_xlogdumpの出力例pg_xlogdump base/pgsql934/pg_xlog/000000010000000000000001
rmgr: Heap len (rec/tot): 35/ 67, tx: 1000, lsn: 0/01B25020, prev 0/01B24FE0, bkp: 0000, desc: insert(init): rel 1663/12297/16384; tid 0/1
rmgr: Transaction len (rec/tot): 12/ 44, tx: 1000, lsn: 0/01B25068, prev 0/01B25020, bkp: 0000, desc: commit: 2014-04-26 19:51:36.311101 JST
rmgr(resource manager)は処理カテゴリのようなもの。len は rec:rmgrに関連するもののみのレコード長
totはトランザクションレコード全体の長さ。txはトランザクションID
bkp はフルページのバックアップをしたかのフラグ。descはトランザクションの処理内容
pg_xlogdump 活用方法?● 運用でお世話になることは少ない・・● フルページの割合の調査には有用か
– Bkpフラグ等で確認できる● rmgrで絞れば、例えばテーブルの
CREATE/DROPなどを抽出できる– 大事なデータやテーブルの削除処理が分かるので、
オペミスからの復旧に使える– 大事な作業はログを取っておくものなので、出番は
ないかも・・
pg_xlogdump 活用方法?pg_xlogdump -r Storage …
rmgr: Storage len (rec/tot): 16/ 48, tx: 0, lsn: 0/0227AA20, prev 0/0227A9F0,bkp: 0000, desc: file create: base/12297/16505
挙動を見てみよう その1● Btreeのリーフスプリット
● Btreeインデックスのスプリットは● 一番右端のリーフは左をFILLFACTORぶん詰める● それ以外は1:1の比率で分ける
リーフ分割
右はなるべく空ける
見てみるcreate table test (c1 int);
CREATE INDEX test_idx ON test(c1);
INSERT into test SELECT generate_series(1,1000);SELECT (bt_page_stats('test_idx', i)).blkno,(bt_page_stats('test_idx', i)).type, (bt_page_stats('test_idx', i)).live_items, (bt_page_stats('test_idx', i)).btpo_prev, (bt_page_stats('test_idx', i)).btpo_next FROM (SELECT generate_series(1, relpages-1) from pg_class WHERE relname = 'test_idx')s(i);
blkno | type | live_items | btpo_prev | btpo_next
-------+------+------------+-----------+-----------
1 | l | 367 | 0 | 2
2 | l | 367 | 1 | 4
3 | r | 3 | 0 | 0
4 | l | 268 | 2 | 0
見てみるINSERT INTO test SELECT 1 FROM generate_series(1,100);
blkno | type | live_items | btpo_prev | btpo_next
-------+------+------------+-----------+-----------
1 | l | 251 | 0 | 5
2 | l | 367 | 5 | 4
3 | r | 4 | 0 | 0
4 | l | 268 | 2 | 0
5 | l | 217 | 1 | 2
左のリーフがスプリットされ251:217のキーを保持
見てみるINSERT INTO test SELECT 1000 FROM generate_series(1,200);
blkno | type | live_items | btpo_prev | btpo_next
-------+------+------------+-----------+-----------
1 | l | 251 | 0 | 5
2 | l | 367 | 5 | 4
3 | r | 5 | 0 | 0
4 | l | 407 | 2 | 6
5 | l | 217 | 1 | 2
6 | l | 62 | 4 | 0
右端のリーフがスプリットされ407:62のキーを保持
挙動を見てみよう その2● Commit Hint Bit
● INSERTやUPDATEで新規のデータが投入される● そのトランザクションがコミットされる● 別のトランザクションがその新規のデータを見る● その際、本当にコミットされたかをコミットログから判断する● コミットされていたらフラグを立て、以降はフラグで判断する● これがCommit Hint Bit
タプルヘッダ 実データTx A
Tx B
INSERT & COMMIT
clog
見に行くHintないClog見る
Commitされてた。フラグ付ける
見てみる● 簡単なデモで
終わりに● PostgreSQLのデータ構成とツールの一部を紹
介しました● データの作りや変更を追っていく
と、PostgreSQLの中が見えてきます● バイナリエディタやgdbを駆使するのもアリで
すが、便利なツールもあります● 是非使ってみてください!
ご清聴ありがとうございました!QA?