Comments
Description
Transcript
PostgreSQL チューニング入門
PostgreSQL チューニング入門 PostgreSQL チューニング入門 c 2003 by Kenji Sugita Copyright ° 1 PostgreSQL チューニング入門 チューニングとは • パフォーマンスの維持 … 問題発生の抑制、異常の発見 – 目的 … 効率と安定性の維持 – 日常の管理 – パフォーマンスの監視 • パフォーマンスの改善 … 問題解決 – 目的 … 効率と安定性の改善及び回復 – 開発時 … 性能目標の達成 – 運用時 … 効率低下やエラーなどの障害への対応 c 2003 by Kenji Sugita Copyright ° 2 PostgreSQL チューニング入門 チューニングに必要なツール (その 1) • PostgreSQL の contrib – pg controldata … コントロールファイルの情報の表示。OID (Object Identifier) と XID (Transaction Identifier) のチェック。 – oid2name … リレーションファイル名とリレーションの対応表示 – pgstattuple … テーブルの不要領域チェック – pgbench … ベンチマーク • PostgreSQL の機能 – EXPLAIN、EXPLAIN ANALYZE – アクセス統計情報 サーバの稼働状況を収集し、報告する機能。逐次スキャンとインデックスス キャンの回数。スキャン・挿入・更新・削除で処理されたタプル数。テーブル とインデックスの読み込みブロック数、バッファヒット数。サーバが処理中の クエリーのモニター。 – psql の \timing コマンド … クライアントから見た正確な実行時間の計測。 c 2003 by Kenji Sugita Copyright ° 3 PostgreSQL チューニング入門 チューニングに必要なツール (その 2) • RedHat、カスタムツール – pg filedump … RedHat。テーブルファイルやインデックスファイルのダン プ。データベースサイズ見積りでのレコードサイズ、インデックスの空間利用 効率の確認。 – pg chkrel … カスタムツール。テーブルとインデックスの不要領域チェック、 テーブル毎のインデックスと TOAST を含むテーブルのディスク使用量を 集計。 – gennum、iterate … カスタムツール。データ生成、繰り返し。単純な大量 データを高速に作成。 c 2003 by Kenji Sugita Copyright ° 4 PostgreSQL チューニング入門 チューニングに必要なツール (その 3) • vmstat … メモリ、スワップ、ディスク • iostat … ディスク入出力 • mpstat … マルチ CPU 稼働状況 • free … メモリ、スワップ • sar (System Activity Reporter) • lsof (List Open Files) … オープンファイルの表示。 • netstat … ネットワーク • ps、top … プロセス • ipcs … 共有メモリ、セマフォ、メッセージキュー c 2003 by Kenji Sugita Copyright ° 5 PostgreSQL チューニング入門 oid2name … リレーションファイル名とリレーションの対応表示 $ oid2name All databases: --------------------------------16976 = sugita 1 = template1 16975 = template0 $ oid2name -d sugita All tables from database "sugita": --------------------------------236159 = class1 $ oid2name -d sugita -x All tables from database "sugita": --------------------------------236159 = class1 16406 = pg_aggregate ... 1247 = pg_type 16650 = pg_type_oid_index 16651 = pg_type_typname_nsp_index 16681 = pg_user 16688 = pg_views 0 = pg_xactlock $ c 2003 by Kenji Sugita Copyright ° $ tree -F data data/ … データベースクラスタ |-- base/ | |-- 1/ … template1 | |-- 16975/ … template0 | ‘-- 16976/ … ユーザデータベース | |-- 1247 … テーブル、インデックス ... シーケンス、TOAST | |-- 236159 ... |-- global/ |-- pg_clog/ |-- pg_hba.conf |-- pg_ident.conf |-- pg_xlog/ |-- postgresql.conf |-- postmaster.opts ‘-- postmaster.pid 7 directories, 284 files $ 6 PostgreSQL チューニング入門 gennum、iterate … データ生成、繰り返し =# SELECT gennum(3); gennum -------0 1 2 (3 rows) =# SELECT gennum(3, 2); gennum -------2 3 4 (3 rows) =# SELECT gennum(3, 2, 2); gennum -------2 4 6 (3 rows) =# SELECT iterate(3); iterate --------- (3 rows) =# c 2003 by Kenji Sugita Copyright ° =# CREATE TABLE class1(id integer, data text); CREATE TABLE =# INSERT INTO class1 SELECT n, rpad(’a’, n % 100, ’b’) -# FROM (SELECT gennum(100000) AS n) AS g; INSERT 0 100000 =# SELECT count(*) FROM class1; count -------100000 (1 row) =# SELECT * FROM class1 ORDER BY id LIMIT 10; id | data ----+----------0 | =# INSERT INTO class1 SELECT (random() * 1000) 1 | a -# FROM (SELECT iterate(100000)) AS i; 2 | ab INSERT 0 100000 3 | abb =# SELECT * FROM class1 LIMIT 10; 4 | abbb id | data 5 | abbbb -----+-----6 | abbbbb 501 | 7 | abbbbbb 158 | 8 | abbbbbbb 566 | 9 | abbbbbbbb 252 | (10 rows) 542 | 890 | =# 318 | 200 | 366 | 207 | (10 rows) =# 7 PostgreSQL チューニング入門 lsof (List Open Files) … オープンファイルの表示。 $ lsof -h lsof 4.60 latest revision: ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/ latest FAQ: ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/FAQ latest man page: ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/lsof_man usage: [-?abChlnNoOPRstUvV] [-c c] [+|-d s] [+D D] [+|-f[cfgGn]] [-F [f]] [-g [s]] [-i [i]] [-k k] [+|-L [l]] [-m m] [+|-M] [-o [o]] [-p s] [+|-r [t]] [-S [t]] [-T [t]] [-u s] [+|-w] [--] [names] Defaults in parentheses; comma-separate set (s) items; dash-separate ranges. -?|-h list help -a AND selections (OR) -b avoid kernel blocks -c c cmd c, /c/[bix] -C no kernel name cache +d s dir s files -d s select by FD set +D D dir D tree *SLOW?* -i select IPv4 files -l list UID numbers -n no host names -N select NFS files -o list file offset -O avoid overhead *RISKY* -P no port names -R list paRent PID -s list file size -t terse listing -T disable TCP/TPI info -U select Unix socket -v list version info -V verbose search +|-w Warnings (+) ... $ lsof -c post COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME postgres 901 sugita cwd VDIR 14,12 1408 1538735 /Volumes/Local (/dev/disk0s12) postgres 901 sugita 0r VCHR 3,2 0t0 42883204 /dev/null postgres 901 sugita 1w VREG 14,10 250937 1261306 /Volumes/Home (/dev/disk0s10) postgres 901 sugita 2w VREG 14,10 250937 1261306 /Volumes/Home (/dev/disk0s10) postgres 901 sugita 3u inet 0x02d3a75c 0t0 TCP *:5432 (LISTEN) postgres 901 sugita 4u unix 0x02cffa78 0t0 ->(none) ... postgres 22999 sugita 39u VREG 14,12 16384 1526279 /Volumes/Local/opt/pgsql/7.3.1/data/global/16643 postgres 22999 sugita 40u VREG 14,12 8192 1526233 /Volumes/Local/opt/pgsql/7.3.1/data/global/1260 ... postgres 22999 sugita 70u VREG 14,12 73728 1526438 /Volumes/Local/opt/pgsql/7.3.1/data/base/16976/16408 postgres 22999 sugita 71u VREG 14,12 16384 1526450 /Volumes/Local/opt/pgsql/7.3.1/data/base/16976/16603 $ c 2003 by Kenji Sugita Copyright ° 8 PostgreSQL チューニング入門 チューニングに必要な知識 • ハードウェア (CPU 種類と数、ディスクの種類、RAID、 …) • OS (入出力、ネットワーク、クラスター …) • データベースシステム – システムカタログ – プロセス構造 – プログラム構造 • SQL • 設計知識 • 業務知識 c 2003 by Kenji Sugita Copyright ° 9 PostgreSQL チューニング入門 日常の管理 • ログ • バックアップ • VACUUM、ANALYZE、インデックス再構築 • ディスク領域の監視と見積り • その他のパフォーマンス調整 c 2003 by Kenji Sugita Copyright ° 10 PostgreSQL チューニング入門 ログ (その 1) • 障害とアクセス状況の監視 – サーバーエラー – クエリーエラー – アクセスログ – クエリーログ • 方法 – syslog 大量のメッセージは、パフォーマンスに影響を与える。 – メッセージのリダイレクト ∗ データベースクラスタと同じディスクに保存するとパフォーマンスに影響 を与える。 ∗ daemontools の multilog コマンド http://cr.yp.to/djb.html ∗ Apache 付属の rotatelogs コマンド c 2003 by Kenji Sugita Copyright ° 11 PostgreSQL チューニング入門 ログ (その 2) multilog - daemontools のログプログラム multilog script スクリプト t -pattern +pattern s# n# !processor dir 行の先頭に TAI64N 形式のタイムスタンプを付ける。tai64nlocal で可読形式に変換 pattern に一致する行を非選択。 pattern に一致する行を選択。 最大ファイルサイズ 4096∼16777215。デフォルト 99999。 最大ログファイル数。デフォルト 10。 フィルタプロッセッサを指定する。 ログの指定。 rotatelogs - Apache ログファイルのローテーションを行う rotatelogs logfile rotationtime [offset] 標準入力からログメッセージを読み込み、ファイルに保存する。ファイルは、指定した 間隔で、ローテーションされる。 オプション logfile ログファイルのパス名。パス名には、strftime の % フォーマット指定を含め ることができる。% 指定がない場合には、ファイル作成時刻から .nnnnnnnnnn 形式のサフィックスが求められ付加される。 rotationtime ローテーション間隔を秒数で指定する。 offset UTC との差を分数で指定する c 2003 by Kenji Sugita Copyright ° 12 PostgreSQL チューニング入門 ログ (その 2) • 関連 GUC – silent mode – syslog (0、0 … 端末、1 … 端末と syslog、2 … syslog) – syslog facility (’LOCAL0’) – syslog ident (’postgres’) – log connections – log duration – log min error statement – log pid – log statement – log timestamp c 2003 by Kenji Sugita Copyright ° 13 PostgreSQL チューニング入門 VACUUM、ANALYZE インデックスの再構築 • VACUUM 不要領域の回収。 • ANALYZE 統計情報の収集。 • インデックスの再構築。 REINDEX、DROP INDEX&CREATE INDEX。 c 2003 by Kenji Sugita Copyright ° 14 PostgreSQL チューニング入門 VACUUM • コンカレントバキューム 運用を妨げずに並行して実行可能 • 空き領域の登録 1 日に 1 回は実行したい。 • XID ラップアラウンドの回避 パラメータを指定しない VACUUM の実行。 • 指標 pgstattuple、pg chkrel。 c 2003 by Kenji Sugita Copyright ° 15 PostgreSQL チューニング入門 ANALYZE • 統計情報の収集 プランナが統計情報とアクセスメソッドの評価関数を用いて、アクセスパスを評 価し、コストベースによる最適な実行プランを選択する。 • 実行タイミング – データを大量に追加、更新、削除したときに実行する。 – 定期的に実行する。 c 2003 by Kenji Sugita Copyright ° 16 PostgreSQL チューニング入門 インデックスの再構築 • DROP INDEX & CREATE INDEX データ量の多いバッチ更新処理がある場合。 • REINDEX – 運用中の実行が可能。 対象テーブルはロックされる。実行時間を調整。 – システムカタログのインデックス再構築。 c 2003 by Kenji Sugita Copyright ° 17 PostgreSQL チューニング入門 ディスク領域の監視と見積り • ディスク領域の監視 – 容量 – ボトルネック • ディスク領域の見積り 単純で正確な方法はまだない。 c 2003 by Kenji Sugita Copyright ° 18 PostgreSQL チューニング入門 テーブル領域と不要領域の計測 (その 1) 整数フィールド 1 つ、主キー。10 万件の内 9 万件を削除。 削除後 ANALYZE =# SELECT * FROM pgstattuple(’class1’); -[ RECORD 1 ]------+-------table_len | 3612672 tuple_count | 10000 tuple_len | 320000 tuple_percent | 8.86 dead_tuple_count | 90000 dead_tuple_len | 2880000 dead_tuple_percent | 79.72 free_space | 3848 free_percent | 0.11 =# VACUUM ANALYZE 後 =# SELECT * FROM pgstattuple(’class1’); -[ RECORD 1 ]------+------table_len | 368640 … テーブルの物理的な大きさ tuple_count | 10000 … タプル数 tuple_len | 320000 … タプル長の合計 tuple_percent | 86.81 … (tuple_len / table_len) x 100 dead_tuple_count | 0 … デッドタプル数 dead_tuple_len | 0 … デッドタプルタプル長の合計 dead_tuple_percent | 0 … (dead_tuple_len / table_len) x 100 free_space | 2882260 … フリースペース free_percent | 79.78 … (free_space / table_len) x 100 =# c 2003 by Kenji Sugita Copyright ° 19 PostgreSQL チューニング入門 テーブル領域と不要領域の計測 (その 2) $ /usr/local/pgsql/tools/scripts/pg_chkrel Date : Thu May 1 15:25:06 JST 2003 Host : papi User : sugita Database Host : default (local) Database Name : sugita (16976) Database User : sugita (1) Database Port : default Database Directory : /opt/pgsql/7.3.1/data Version : PostgreSQL 7.3.1 on powerpc-apple-darwin6.4, compiled by GCC gcc (GCC) 3.1 20020420 (prerelease) Page Size (KB) : 8 (default) Relation Name r pg_catalog.pg_aggregate i pg_catalog.pg_aggregate_fnoid_index ... 削除後 ANALYZE r public.class1 i public.class1_pkey VACUUM ANALYZE 後 r public.class1 i public.class1_pkey REINDEX 後 r public.class1 i public.class1_pkey VACUUM FULL 後 r public.class1 i public.class1_pkey REINDEX 後 r public.class1 i public.class1_pkey ... c 2003 by Kenji Sugita Copyright ° File Name Tuples 16406 16600 Pages File Size Size/Tuples Tuple Size 8 0.133 0.027 16 0.133 -.--- 60 60 1 ( 2 ( 3) 2) 1247353 1247355 3065 1000 441 ( 1 ( 442) 1) 3528 2448 1.151 2.440 0.004 -.--- 1247353 1247355 10000 10000 441 ( 306 ( 747) 306) 3528 2448 0.353 0.244 0.004 -.--- 1247353 1347357 10000 10000 441 ( 24 ( 465) 24) 3528 192 0.353 0.018 0.004 -.--- 1247353 1347357 10000 10000 45 ( 47 ( 92) 47) 360 376 0.036 0.037 0.004 -.--- 1247353 1347358 10000 10000 45 ( 24 ( 69) 24) 360 192 0.036 0.018 0.004 -.--- 20 PostgreSQL チューニング入門 その他のパフォーマンス調整 (その 1) • フリースペースマップ – max fsm pages … 必要ディスク容量 (バイト) / 8192 – max fsm relations • ファイルディスクリプタキャッシュ – max files per process • WAL – wal sync method … pg bench を用いる – commit delay – commit siblings • コネクション数 – max connections – superuser reserved connections c 2003 by Kenji Sugita Copyright ° 21 PostgreSQL チューニング入門 wal sync method パラメータ (Solaris 2.6) c 2003 by Kenji Sugita Copyright ° 22 PostgreSQL チューニング入門 その他のパフォーマンス調整 (その 2) • 共有バッファ – shared buffers • ワークメモリ – sort mem – vacuum mem c 2003 by Kenji Sugita Copyright ° 23 PostgreSQL チューニング入門 その他のパフォーマンス調整 (GEQO その 1) • Pool Size 個体数 (解のとりうる空間中の解の候補の数)。pool は個体の入れものを指す。 解の多様性に関わる。大きな値にすると多くのパターンについて調べることがで きるので、よい解が発見される可能性が高くなるが、計算量も増加する。 多様性は数だけでなく解の候補の初期状態の多様性にも依存する。PostgreSQL では、解の候補の初期状態を一様乱数によって決めている。 • Generations 世代数 (計算回数)。 解の収束の遅い問題では大きく設定するが、速く収束する問題では大きくすると 無駄な計算を繰り返す。 PostgreSQL では解の収束条件がなく、常に Generations の回数の計算を行う。 c 2003 by Kenji Sugita Copyright ° 24 PostgreSQL チューニング入門 その他のパフォーマンス調整 (GEQO その 2) • Selection Bias 通常の GA では、子の選択をするが PostgreSQL では親の選択を行っている。そ の親の選択時のバイアス。変域は [1.5, 2.0] で、大きい程評価 の高い親が選択さ れる確率が大きくなる。50% 確率は 1.5 で上位 38.2%、2.0 で上位 29.3%。バイ アスカーブは次の関数が用いられている。 p=b− p b2 − 4(b − 1)r p: 値域 [0, 1.0] のバイアスのかかった乱数 b: 変域 [1.5, 2.0] のバイアス係数 r: 定義域 [0, 1.0] の一様乱数 c 2003 by Kenji Sugita Copyright ° 25 PostgreSQL チューニング入門 その他のパフォーマンス調整 (GEQO その 3) • GEQO のアルゴリズム 解の候補を用意し、コスト (評価値) の順に並べる。 while (Generations 回繰り返す) { ・親を選択 (解の候補を 2 つ選択) ・ERX を行う。 ・子のコストを求める。 ・pool に、子を入れ、最低コストの解を取り出す。 } ERX (Edge Recombination Crossover) … 辺再組合せ交叉、親を辺分解し、親の 共通辺を残すように再組合せした交叉。他の交叉のコードも書かれてるがデフォ ルトではコンパイルされない。 c 2003 by Kenji Sugita Copyright ° 26 PostgreSQL チューニング入門 その他のパフォーマンス調整 (GEQO その 4) • 関連 GUC – geqo – geqo effort – geqo generations – geqo pool size – geqo random seed – geqo selection bias – geqo threshold c 2003 by Kenji Sugita Copyright ° 27 PostgreSQL チューニング入門 パフォーマンスの監視 (その 1) • データ量の変化を監視 – 最善は、全数試験 – 予想と合っているか – 予想するにはどうするか – 予想と違う原因 ∗ 想定外のデータ ∗ 見積り方法が確立していない • データの質がパフォーマンスを変える – 予想と違う性質になる可能性がある – 予想と違って来ていることを見逃さないようにする – 変わってしまったならば、チューニングが必要 • データ量と質の変化で、データベースの設計ミスがデータの増加で露見 c 2003 by Kenji Sugita Copyright ° 28 PostgreSQL チューニング入門 パフォーマンスの監視 (その 2) • EXPLAIN による監視 定期的に、システムで使用される典型的なクエリーの EXPLAIN の結果を監視し、 チェックする。 – インデックスが使われなくなっていないか – 変化していたならば、それは妥当かどうか – 件数の多いソートが頻発していないか • 必要に応じて、実行時間の計測 \timing コマンド • アクセス統計情報による監視 • 統計情報の妥当性の監視 c 2003 by Kenji Sugita Copyright ° 29 PostgreSQL チューニング入門 アクセス統計情報 (その 1) • バックエンドアクティビティ • アクセス統計情報 – シーケンシャルスキャン数 – インデックススキャン数 ∗ インデックスが使用されているか ∗ 未使用インデックスの特定 … ディスクの無駄、更新時の負荷増加 – 挿入・更新・削除タプル数 • I/O 統計情報 – 読み込みディスクブロック数 – 読み込みディスクブロックのキャッシュヒット数 c 2003 by Kenji Sugita Copyright ° 30 PostgreSQL チューニング入門 アクセス統計情報 (その 2) • 関連 GUC – stats block level – stats command string – stats reset on server start – stats row level – stats start collector c 2003 by Kenji Sugita Copyright ° 31 PostgreSQL チューニング入門 アクセス統計情報 (その 3) =# CREATE TABLE class1 (id integer); CREATE TABLE =# INSERT INTO class1 SELECT gennum(100000); INSERT 0 100000 =# SELECT * FROM pg_stat_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]-+------relid | 436186 schemaname | sugita relname | class1 seq_scan | 0 seq_tup_read | 0 idx_scan | idx_tup_fetch | n_tup_ins | 100000 n_tup_upd | 0 n_tup_del | 0 =# SELECT count(*) FROM class1; -[ RECORD 1 ]count | 100000 =# SELECT * FROM pg_stat_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]-+------relid | 436186 schemaname | sugita relname | class1 seq_scan | 2 seq_tup_read | 200000 idx_scan | 0 idx_tup_fetch | 0 n_tup_ins | 100000 n_tup_upd | 0 n_tup_del | 0 =# CREATE INDEX class1_id_index ON class1(id); CREATE INDEX =# SELECT * FROM pg_stat_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]-+------relid | 436186 schemaname | sugita relname | class1 seq_scan | 1 seq_tup_read | 100000 idx_scan | 0 idx_tup_fetch | 0 n_tup_ins | 100000 n_tup_upd | 0 n_tup_del | 0 c 2003 by Kenji Sugita Copyright ° 32 PostgreSQL チューニング入門 アクセス統計情報 (その 4) =# SELECT * FROM class1 ORDER BY id LIMIT 1; -[ RECORD 1 ] id | 0 =# SELECT * FROM pg_stat_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]-+------relid | 436186 schemaname | sugita relname | class1 seq_scan | 2 seq_tup_read | 200000 idx_scan | 1 idx_tup_fetch | 2 n_tup_ins | 100000 n_tup_upd | 0 n_tup_del | 0 =# SELECT * FROM class1 ORDER BY id DESC LIMIT 1; -[ RECORD 1 ] id | 99999 =# SELECT * FROM pg_stat_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]-+------relid | 436186 schemaname | sugita relname | class1 seq_scan | 2 seq_tup_read | 200000 idx_scan | 2 idx_tup_fetch | 4 n_tup_ins | 100000 n_tup_upd | 0 n_tup_del | 0 c 2003 by Kenji Sugita Copyright ° 33 PostgreSQL チューニング入門 アクセス統計情報 (その 5) =# CREATE TABLE class1 (id integer); CREATE TABLE =# INSERT INTO class1 SELECT gennum(1000000); INSERT 0 1000000 =# SELECT * FROM pg_statio_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 4406 heap_blks_hit | 999999 idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | =# CREATE INDEX class1_id_index ON class1(id); CREATE INDEX =# SELECT * FROM pg_statio_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 8812 heap_blks_hit | 999999 idx_blks_read | 2194 idx_blks_hit | 0 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | c 2003 by Kenji Sugita Copyright ° =# SELECT count(*) FROM class1; -[ RECORD 1 ]-count | 1000000 =# SELECT * FROM pg_statio_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 13218 heap_blks_hit | 999999 idx_blks_read | 2194 idx_blks_hit | 0 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | =# SELECT * FROM class1 ORDER BY id DESC LIMIT 1; -[ RECORD 1 ] id | 999999 -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 13218 heap_blks_hit | 1000001 idx_blks_read | 2198 idx_blks_hit | 0 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | 34 PostgreSQL チューニング入門 アクセス統計情報 (その 6) =# SELECT * FROM class1 ORDER BY ID DESC LIMIT 1; -[ RECORD 1 ] id | 999999 =# SELECT * FROM pg_statio_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 13218 heap_blks_hit | 1000003 idx_blks_read | 2198 idx_blks_hit | 4 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | =# SELECT * FROM class1 ORDER BY id LIMIT 1; -[ RECORD 1 ] id | 0 =# SELECT * FROM pg_statio_all_tables WHERE relname = ’class1’; -[ RECORD 1 ]---+-------relid | 5347401 schemaname | public relname | class1 heap_blks_read | 13219 heap_blks_hit | 1000004 idx_blks_read | 2200 idx_blks_hit | 6 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | =# c 2003 by Kenji Sugita Copyright ° 35 PostgreSQL チューニング入門 パフォーマンスチューニング • チューニング対象 – OS – データベースシステム ディスク配置、GUC、インデックス – クエリー (一番問題が多い) … EXPLAIN による実行計画分析 – 処理フロー – データベース設計 c 2003 by Kenji Sugita Copyright ° 36 PostgreSQL チューニング入門 OS チューニング • 共有メモリ量 • オープンファイル数 • ファイルシステム – 種類 – 最終アクセスタイム – ジャーナル設定 – write cache c 2003 by Kenji Sugita Copyright ° 37 PostgreSQL チューニング入門 ディスク分割 • OS、PostgreSQL のバイナリ、アプリケーション。 • データベースクラスタの分割 – ディスクを分離して、一般的には、どれだけ効果があるかは明確でない。シス テム毎に試さないと効果は判断できない。 – PostgreSQL は、効果的なディスク分割ができない。tablespaces が必要。 data/ … データベースクラスタ ○ |-- base/ | |-- 1/ … template1 | |-- 16975/ … template0 | ‘-- 16976/ … ユーザデータベース | |-- 1247 … テーブル、インデックス、シーケンス、TOAST | |-- 1249 ... | |-- 16680 | |-- PG_VERSION | |-- pg_internal.init | ‘-- pgsql_tmp/ … ソートとハッシュのワークディレクトリ ○ |-- global/ … グローバルテーブル、pg_control、pgstat.stat ○ |-- pg_clog/ … コミットログ ○ ‘-- pg_xlog/ … WAL ○ c 2003 by Kenji Sugita Copyright ° 38 PostgreSQL チューニング入門 EXPLAIN (その 1) • EXPLAIN – 実行計画 – 最初のタプルが返る迄の予測コスト – 全タプルが返る迄の予測コスト – 結果の予測行数 – 結果の予測タプルサイズ • EXPLAIN ANALYZE – 実行計画 – 実測値 … クエリーの実行時間とは異なる – 最初のタプルが返る迄の時間 – 全タプルが返る迄の時間 – 結果の行数 – クエリーオペレータの繰り返し回数 c 2003 by Kenji Sugita Copyright ° 39 PostgreSQL チューニング入門 EXPLAIN (その 2) SELECT t1.typname AS castsource, t2.typname AS casttarget, p.proname AS proname, p.provolatile AS provolatile, c.castcontext AS castcontext FROM pg_type t1, pg_type t2, pg_cast c, pg_proc p WHERE c.castsource = t1.oid AND c.casttarget = t2.oid AND c.castfunc = p.oid AND t1.typname = ’bit’ ORDER BY 1, 2 ; EXPLAIN: QUERY PLAN --------------------------------------------------------------------------------------------------------------------------Sort (cost=21.77..21.78 rows=1 width=218) Sort Key: t1.typname, t2.typname -> Nested Loop (cost=5.50..21.76 rows=1 width=218) -> Nested Loop (cost=5.50..15.73 rows=1 width=149) -> Hash Join (cost=5.50..10.12 rows=1 width=81) Hash Cond: ("outer".castsource = "inner".oid) -> Seq Scan on pg_cast c (cost=0.00..3.74 rows=174 width=13) -> Hash (cost=5.49..5.49 rows=1 width=68) -> Index Scan using pg_type_typname_nsp_index on pg_type t1 (cost=0.00..5.49 rows=1 width=68) Index Cond: (typname = ’bit’::name) -> Index Scan using pg_type_oid_index on pg_type t2 (cost=0.00..5.57 rows=1 width=68) Index Cond: ("outer".casttarget = t2.oid) -> Index Scan using pg_proc_oid_index on pg_proc p (cost=0.00..5.98 rows=1 width=69) Index Cond: ("outer".castfunc = p.oid) c 2003 by Kenji Sugita Copyright ° 40 PostgreSQL チューニング入門 EXPLAIN (その 3) EXPLAIN ANALYZE: QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------Sort (cost=21.77..21.78 rows=1 width=218) (actual time=54.44..54.45 rows=2 loops=1) Sort Key: t1.typname, t2.typname -> Nested Loop (cost=5.50..21.76 rows=1 width=218) (actual time=41.26..47.14 rows=2 loops=1) -> Nested Loop (cost=5.50..15.73 rows=1 width=149) (actual time=27.16..28.48 rows=3 loops=1) -> Hash Join (cost=5.50..10.12 rows=1 width=81) (actual time=27.07..28.21 rows=3 loops=1) Hash Cond: ("outer".castsource = "inner".oid) -> Seq Scan on pg_cast c (cost=0.00..3.74 rows=174 width=13) (actual time=6.97..9.11 rows=174 loops=1) -> Hash (cost=5.49..5.49 rows=1 width=68) (actual time=17.89..17.89 rows=0 loops=1) -> Index Scan using pg_type_typname_nsp_index on pg_type t1 (cost=0.00..5.49 rows=1 width=68) (actual time=17.78..17.80 rows=1 loops=1) Index Cond: (typname = ’bit’::name) -> Index Scan using pg_type_oid_index on pg_type t2 (cost=0.00..5.57 rows=1 width=68) (actual time=0.04..0.05 rows=1 loops=3) Index Cond: ("outer".casttarget = t2.oid) -> Index Scan using pg_proc_oid_index on pg_proc p (cost=0.00..5.98 rows=1 width=69) (actual time=6.18..6.19 rows=1 loops=3) Index Cond: ("outer".castfunc = p.oid) Total runtime: 55.81 msec Time: 88.98 ms castsource | casttarget | proname | provolatile | castcontext ------------+------------+---------+-------------+------------bit | int4 | int4 | i | e bit | int8 | int8 | i | e Time: 41.05 ms c 2003 by Kenji Sugita Copyright ° 41 PostgreSQL チューニング入門 クエリーオペレータ (その 1) Seq Scan Index Scan Tid Scan Nested Loop Merge Join Hash Join、Hash c 2003 by Kenji Sugita Copyright ° Sort Group Unique Aggregate Limit Append Materialize Result Subplan Subquery Scan Function Scan Setop Intersect Intersect All Except Except All 42 PostgreSQL チューニング入門 クエリーオペレータ (その 2) =# \d pg_proc Table "pg_catalog.pg_proc" Column | Type | Modifiers --------------+-----------+----------proname | name | not null pronamespace | oid | not null proowner | integer | not null prolang | oid | not null proisagg | boolean | not null prosecdef | boolean | not null proisstrict | boolean | not null proretset | boolean | not null provolatile | "char" | not null pronargs | smallint | not null prorettype | oid | not null proargtypes | oidvector | not null prosrc | text | probin | bytea | proacl | aclitem[] | Indexes: pg_proc_oid_index unique btree pg_proc_proname_args_nsp_index 関数名 ネームスペース名 関数のオーナのデータベースユーザ id 記述言語、または、呼び出しインターフェースの oid true ならば、集約関数 true ならば、関数のオーナ権限で実行 true ならば、引数が NULL の場合に NULL を返す true ならば、集合を返す IMMUTABLE | STABLE | VOLATILE 引数の数 戻り値のデータ型の oid 引数のデータ型の oid の配列 関数ハンドラが使用する関数呼び出し方法 関数呼び出し方法の付加情報 関数アクセス権 (oid), unique btree (proname, pronargs, proargtypes, pronamespace) =# c 2003 by Kenji Sugita Copyright ° 43 PostgreSQL チューニング入門 クエリーオペレータ (その 3) -- Seq Scan … シーケンシャルスキャン SELECT * from pg_proc; QUERY PLAN ------------------------------------------------------------Seq Scan on pg_proc (cost=0.00..73.07 rows=1507 width=311) -- Index Scan … インデックススキャン SELECT * from pg_proc WHERE proname = ’max’; QUERY PLAN -------------------------------------------------------------------------------------------------Index Scan using pg_proc_proname_args_nsp_index on pg_proc (cost=0.00..59.35 rows=16 width=311) Index Cond: (proname = ’max’::name) -- Tid Scan … ページ番号とページ内インデックスによるスキャン SELECT * from pg_proc WHERE ctid = ’(7,24)’; QUERY PLAN --------------------------------------------------------Tid Scan on pg_proc (cost=0.00..4.01 rows=1 width=311) Filter: (ctid = ’(7,24)’::tid) c 2003 by Kenji Sugita Copyright ° 44 PostgreSQL チューニング入門 クエリーオペレータ (その 4) -- Nested Loop … 入れ子反復結合 DROP TABLE class1; CREATE TABLE class1 (id integer); DROP TABLE class2; CREATE TABLE class2 (id integer); INSERT CREATE INSERT CREATE INTO class1 SELECT gennum(1000); INDEX class1_id_index ON class1(id); INTO class2 SELECT random() * 10000 FROM (SELECT iterate(10000)) AS i; INDEX class2_id_index ON class2(id); VACUUM ANALYZE; SELECT c1.id AS ‘‘c1.id’’, c2.id AS ‘‘c2.id’’ FROM class1 c1, class2 c2 WHERE c1.id < 5 AND c2.id < 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------Nested Loop (cost=0.00..34.50 rows=24 width=8) (actual time=1.32..8.02 rows=55 loops=1) -> Index Scan using class2_id_index on class2 c2 (cost=0.00..19.88 rows=5 width=4) (actual time=0.46..1.62 rows=11 loops=1) Index Cond: (id < 10) -> Index Scan using class1_id_index on class1 c1 (cost=0.00..3.07 rows=5 width=4) (actual time=0.10..0.15 rows=5 loops=11) Index Cond: (id < 5) c 2003 by Kenji Sugita Copyright ° 45 PostgreSQL チューニング入門 クエリーオペレータ (その 5) -- Merge Join … マージソート結合 DROP TABLE class1; CREATE TABLE class1 (id integer); CREATE INDEX class1_id_index ON class1(id); INSERT INTO class1 SELECT gennum(1000); DROP TABLE class2; CREATE TABLE class2 (id integer); CREATE INDEX class2_id_index ON class2(id); INSERT INTO class2 SELECT gennum(100); VACUUM analyze; SELECT c1.id AS ‘‘c1.id’’, c2.id AS ‘‘c2.id’’ FROM class1 c1, class2 c2 WHERE c1.id = c2.id; QUERY PLAN ------------------------------------------------------------------------------------------Merge Join (cost=0.00..7.95 rows=100 width=8) Merge Cond: (‘‘outer’’.id = ‘‘inner’’.id) -> Index Scan using class1_id_index on class1 c1 (cost=0.00..21.00 rows=1000 width=4) -> Index Scan using class2_id_index on class2 c2 (cost=0.00..4.10 rows=100 width=4) c 2003 by Kenji Sugita Copyright ° 46 PostgreSQL チューニング入門 クエリーオペレータ (その 6) -- Hash Join、Hash … ハッシュ結合 DROP TABLE class1; CREATE TABLE class1 (id integer); DROP TABLE class2; CREATE TABLE class2 (id integer); CREATE INDEX class2_id_index ON class2(id); INSERT INTO class1 SELECT gennum(1000); INSERT INTO class2 SELECT gennum(100) FROM (SELECT iterate(10)) AS i; VACUUM ANALYZE; SELECT * FROM class1 c1, class2 c2 WHERE c1.id = c2.id; QUERY PLAN ------------------------------------------------------------------------Hash Join (cost=17.50..50.00 rows=1000 width=8) Hash Cond: (‘‘outer’’.id = ‘‘inner’’.id) -> Seq Scan on class2 c2 (cost=0.00..15.00 rows=1000 width=4) -> Hash (cost=15.00..15.00 rows=1000 width=4) -> Seq Scan on class1 c1 (cost=0.00..15.00 rows=1000 width=4) -- Sort … ソート SELECT * FROM pg_proc ORDER BY proname; QUERY PLAN ------------------------------------------------------------------Sort (cost=152.62..156.39 rows=1507 width=311) Sort Key: proname -> Seq Scan on pg_proc (cost=0.00..73.07 rows=1507 width=311) c 2003 by Kenji Sugita Copyright ° 47 PostgreSQL チューニング入門 クエリーオペレータ (その 7) -- Group, Aggregate -- PostgreSQL 7.3 SELECT proname, count(*) AS duplicates FROM pg_proc GROUP BY proname HAVING count(*) > 1; QUERY PLAN -----------------------------------------------------------------------------Aggregate (cost=152.62..167.69 rows=151 width=64) Filter: (count(*) > 1) -> Group (cost=152.62..160.16 rows=1507 width=64) -> Sort (cost=152.62..156.39 rows=1507 width=64) Sort Key: proname -> Seq Scan on pg_proc (cost=0.00..73.07 rows=1507 width=64) -- PostgreSQL 7.4devel SELECT proname, count(*) AS duplicates FROM pg_proc GROUP BY proname HAVING count(*) > 1; QUERY PLAN -----------------------------------------------------------------HashAggregate (cost=85.39..94.47 rows=1210 width=64) Filter: (count(*) > 1) -> Seq Scan on pg_proc (cost=0.00..74.08 rows=1508 width=64) -- Unique SELECT DISTINCT proname FROM pg_proc; QUERY PLAN -----------------------------------------------------------------------Unique (cost=152.62..160.16 rows=151 width=64) -> Sort (cost=152.62..156.39 rows=1507 width=64) Sort Key: proname -> Seq Scan on pg_proc (cost=0.00..73.07 rows=1507 width=64) c 2003 by Kenji Sugita Copyright ° 48 PostgreSQL チューニング入門 クエリーオペレータ (その 8) -- Limit SELECT relname, relpages FROM pg_class ORDER BY relpages DESC LIMIT 10; QUERY PLAN ----------------------------------------------------------------------Limit (cost=8.55..8.58 rows=10 width=68) -> Sort (cost=8.55..8.86 rows=124 width=68) Sort Key: relpages -> Seq Scan on pg_class (cost=0.00..4.24 rows=124 width=68) c 2003 by Kenji Sugita Copyright ° 49 PostgreSQL チューニング入門 クエリーオペレータ (その 9) -- Append, Subquery Scan SELECT proname, oid FROM pg_proc WHERE proname = ’max’ UNION SELECT proname, oid FROM pg_proc WHERE proname = ’min’; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------Unique (cost=119.50..119.74 rows=3 width=68) -> Sort (cost=119.50..119.58 rows=32 width=68) Sort Key: proname, oid -> Append (cost=0.00..118.70 rows=32 width=68) -> Subquery Scan "*SELECT* 1" (cost=0.00..59.35 rows=16 width=68) -> Index Scan using pg_proc_proname_args_nsp_index on pg_proc (cost=0.00..59.35 rows=16 width=68) Index Cond: (proname = ’max’::name) -> Subquery Scan "*SELECT* 2" (cost=0.00..59.35 rows=16 width=68) -> Index Scan using pg_proc_proname_args_nsp_index on pg_proc (cost=0.00..59.35 rows=16 width=68) Index Cond: (proname = ’min’::name) -- Materialize, Subplan SELECT proname, oid FROM pg_proc WHERE proname IN (SELECT proname FROM pg_proc WHERE proname ~ ’^macaddr’); QUERY PLAN ------------------------------------------------------------------------------------------------------------Seq Scan on pg_proc (cost=0.00..9078.84 rows=754 width=68) Filter: (subplan) SubPlan -> Materialize (cost=5.97..5.97 rows=1 width=64) -> Index Scan using pg_proc_proname_args_nsp_index on pg_proc (cost=0.00..5.97 rows=1 width=64) Index Cond: ((proname >= ’macaddr’::name) AND (proname < ’macadds’::name)) Filter: (proname ~ ’^macaddr’::text) c 2003 by Kenji Sugita Copyright ° 50 PostgreSQL チューニング入門 クエリーオペレータ (その 10) -- Result SELECT pg_backend_pid(); QUERY PLAN -----------------------------------------Result (cost=0.00..0.01 rows=1 width=0) =# -- Function Scan SELECT * FROM pg_lock_status() AS (relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean); QUERY PLAN -----------------------------------------------------------------------Function Scan on pg_lock_status (cost=0.00..12.50 rows=1000 width=49) c 2003 by Kenji Sugita Copyright ° 51 PostgreSQL チューニング入門 クエリーオペレータ (その 11) SELECT gennum(2); gennum -------0 1 SELECT gennum(2, 1); gennum -------1 2 -- Intersect, Intersect All, Except, Except All (SELECT gennum(2) UNION ALL SELECT gennum(2)) INTERSECT (SELECT gennum(2, 1) UNION ALL SELECT gennum(2, 1)); QUERY PLAN -------------------------------------------------------------------------------------------SetOp Intersect (cost=0.08..0.10 rows=1 width=0) -> Sort (cost=0.08..0.09 rows=4 width=0) Sort Key: gennum -> Append (cost=0.00..0.04 rows=4 width=0) -> Result (cost=0.00..0.02 rows=2 width=0) -> Append (cost=0.00..0.02 rows=2 width=0) -> Subquery Scan "*SELECT* 1" (cost=0.00..0.01 rows=1 width=0) -> Result (cost=0.00..0.01 rows=1 width=0) -> Subquery Scan "*SELECT* 2" (cost=0.00..0.01 rows=1 width=0) -> Result (cost=0.00..0.01 rows=1 width=0) -> Result (cost=0.00..0.02 rows=2 width=0) -> Append (cost=0.00..0.02 rows=2 width=0) -> Subquery Scan "*SELECT* 3" (cost=0.00..0.01 rows=1 width=0) -> Result (cost=0.00..0.01 rows=1 width=0) -> Subquery Scan "*SELECT* 4" (cost=0.00..0.01 rows=1 width=0) -> Result (cost=0.00..0.01 rows=1 width=0) c 2003 by Kenji Sugita Copyright ° 52 PostgreSQL チューニング入門 プランナの制御 • PostgreSQL では、プランナに詳細な指示をすることはできない • 統計情報を正確にするのが基本 • GUC によるプランナの制御 enable_hashjoin enable_indexscan enable_mergejoin enable_nestloop enable_seqscan enable_sort enable_tidscan • JOIN で、明示的な結合順序を指定する c 2003 by Kenji Sugita Copyright ° 53 PostgreSQL チューニング入門 EXPLAIN によるチューニング (その 1) CREATE CREATE CREATE CREATE TABLE INDEX TABLE INDEX master (id text); master_id_index ON master(id); slave (id text); slave_id_index ON slave(id); INSERT INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO INTO master master master master master master master master INSERT INSERT INSERT INSERT INSERT INSERT INSERT INTO INTO INTO INTO INTO INTO INTO slave slave slave slave slave slave slave SELECT VALUES VALUES VALUES VALUES VALUES VALUES SELECT SELECT VALUES VALUES VALUES VALUES VALUES VALUES n::text FROM (SELECT gennum(0, 10000) AS n) AS g; (’10000’); (’10000’); (’10000’); (’10000’); (’10000’); (’10000’); n::text FROM (SELECT gennum(10000, 10000) AS n) AS g; gennum(1000); (’10000’); (’10000’); (’10000’); (’11000’); (’11000’); (’11000’); VACUUM ANALYZE; c 2003 by Kenji Sugita Copyright ° 54 PostgreSQL チューニング入門 EXPLAIN によるチューニング (その 2) SELECT * FROM master WHERE id IN (SELECT DISTINCT id FROM slave WHERE id = ’10000’); id ------10000 10000 10000 10000 10000 10000 10000 (7 rows) Time: 32.05 ms EXPLAIN ANALYZE SELECT * FROM MASTER WHERE id IN (SELECT DISTINCT id FROM slave WHERE id = ’10000’); QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------Seq Scan on master (cost=0.00..61107.88 rows=5003 width=9) (actual time=0.12..50.12 rows=7 loops=1) Filter: (subplan) SubPlan -> Materialize (cost=6.09..6.09 rows=1 width=6) (actual time=0.00..0.00 rows=1 loops=10006) -> Unique (cost=0.00..6.09 rows=1 width=6) (actual time=0.06..0.08 rows=1 loops=1) -> Index Scan using slave_id_index on slave (cost=0.00..6.08 rows=3 width=6) (actual time=0.06..0.07 rows=3 loops=1) Index Cond: (id = ’10000’::text) Total runtime: 50.56 msec c 2003 by Kenji Sugita Copyright ° 55 PostgreSQL チューニング入門 EXPLAIN によるチューニング (その 3) SELECT master.id FROM master, (SELECT DISTINCT id FROM slave WHERE id = ’10000’) AS s WHERE s.id = master.id; id ------10000 10000 10000 10000 10000 10000 10000 (7 rows) Time: 2.44 ms EXPLAIN ANALYZE SELECT master.id FROM master, (SELECT DISTINCT id FROM slave WHERE id = ’10000’) AS s WHERE s.id = master.id; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------Nested Loop (cost=0.00..9.12 rows=1 width=41) (actual time=0.09..0.16 rows=7 loops=1) -> Subquery Scan s (cost=0.00..6.09 rows=1 width=6) (actual time=0.06..0.07 rows=1 loops=1) -> Unique (cost=0.00..6.09 rows=1 width=6) (actual time=0.05..0.07 rows=1 loops=1) -> Index Scan using slave_id_index on slave (cost=0.00..6.08 rows=3 width=6) (actual time=0.05..0.06 rows=3 loops=1) Index Cond: (id = ’10000’::text) -> Index Scan using master_id_index on master (cost=0.00..3.01 rows=1 width=9) (actual time=0.02..0.06 rows=7 loops=1) Index Cond: (‘‘outer’’.id = master.id) Total runtime: 0.33 msec c 2003 by Kenji Sugita Copyright ° 56 PostgreSQL チューニング入門 レコードサイズの大きい場合のチューニング (その 1) 1. 2400 回の更新で、実行時間が 10 倍 2. カラム数が数百 3. pg filedump で、テーブルを見ると 1 ブロックに 1 レコードで、半分は空きス ペース 4. アクセス統計情報で、読み込みブロック数が多く、ヒット率が低い。 5. VACUUM と REINDEX で元の速度 6. shared buffers を増やすことで実行時間が 7 倍 7. ブロッキングが効かないためインデックスの不要エントリによる極端な速度低下 が発生 暫定的な対処 … VACUUM 回数と shared buffers を増やす。 8. ブロックサイズを 32k に変更 9. 1 ブロックに 7 レコードとなる 10. 実行時間が 2 倍 11. shared buffers を増やし、10% の時間増に改善 c 2003 by Kenji Sugita Copyright ° 57 PostgreSQL チューニング入門 レコードサイズの大きい場合のチューニング (その 2) $ pg_filedump 2347381 ***************************************************************** * PostgreSQL File/Block Formatted Dump Utility * * File: 2347381 * Options used: None * * Dump created on: Fri May 2 09:55:08 2003 ***************************************************************** Block 2 ****************************************************** <Header> ----Block Offset: 0x00004000 Offsets: Lower 24 (0x0018) Block Size: 8192 Upper 3972 (0x0f84) LSN: logid 0 recoff 0x2480c1a4 Special 8192 (0x2000) Items: 1 Free Space: 3948 Length (including item array): 28 <Data> -----Item 1 -- Length: 4218 Offset: 3972 (0x0f84) Flags: USED Block 0 ****************************************************** <Header> ----Block Offset: 0x00000000 Offsets: Lower 24 (0x0018) Block Size: 8192 Upper 3964 (0x0f7c) LSN: logid 0 recoff 0x24809fe8 Special 8192 (0x2000) Items: 1 Free Space: 3940 Length (including item array): 28 Block 3 ****************************************************** <Header> ----Block Offset: 0x00006000 Offsets: Lower 24 (0x0018) Block Size: 8192 Upper 3972 (0x0f84) LSN: logid 0 recoff 0x2480d260 Special 8192 (0x2000) Items: 1 Free Space: 3948 Length (including item array): 28 <Data> -----Item 1 -- Length: 4226 <Data> -----Item 1 -- Length: 4218 Offset: 3964 (0x0f7c) Flags: USED Offset: 3972 (0x0f84) Flags: USED Block 1 ****************************************************** <Header> ----Block Offset: 0x00002000 Offsets: Lower 24 (0x0018) Block Size: 8192 Upper 3964 (0x0f7c) LSN: logid 0 recoff 0x2480b0d4 Special 8192 (0x2000) Items: 1 Free Space: 3940 Length (including item array): 28 <Data> -----Item 1 -- Length: 4226 Offset: 3964 (0x0f7c) c 2003 by Kenji Sugita Copyright ° Flags: USED 58 PostgreSQL チューニング入門 レコードサイズの大きい場合のチューニング (その 3) =# select * from pg_statio_user_tables; -[ RECORD 1 ]---+--------------relid | 16558 relname | largerecord heap_blks_read | 12699 heap_blks_hit | 2213 idx_blks_read | 545 idx_blks_hit | 181 toast_blks_read | 1 toast_blks_hit | 1 tidx_blks_read | 3 tidx_blks_hit | 2 =# =# select * from pg_statio_user_tables; -[ RECORD 1 ]---+--------------relid | 16555 relname | largerecord heap_blks_read | 756 heap_blks_hit | 7988 idx_blks_read | 404 idx_blks_hit | 76 toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit | =# c 2003 by Kenji Sugita Copyright ° 59