TOASTテーブルの成長が制御不能-FULLVACは何もしません


9

最近、自動バキューム機能を利用して他の30個のPGSQLサーバーと連携するために、PostgreSQL 8.2.11サーバーを8.4にアップグレードしました。これは、ハードウェアを管理する別のITグループによって行われたため、他のアップグレードを選択する余地はほとんどありません(しばらくの間、9以上は表示されません)。サーバーは非常に閉じた環境(孤立したネットワーク、限られたroot権限)に存在し、RHEL5.5(i686)で実行されます。アップグレード後、データベースは常に1日あたり5〜6 GBに成長しています。通常、データベース全体では、約20GBです。現在、それは〜89GBです。同等のデータベースを実行し、実際にサードパーティのアプリケーションを介してレコードを相互に同期するサーバーがいくつかあります(1つは内部の仕組みにアクセスできません)。他のデータベースは、本来あるべきように〜20GBです。

次のSQLを実行すると、特定のテーブル、具体的にはそのTOASTテーブルに問題があることはかなり明白です。

SELECT nspname || '.' || relname AS "relation",
    pg_size_pretty(pg_relation_size(C.oid)) AS "size"
  FROM pg_class C
  LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
  WHERE nspname NOT IN ('pg_catalog', 'information_schema')
  ORDER BY pg_relation_size(C.oid) DESC
  LIMIT 20;

生成されるもの:

              関係| サイズ  
------------------------------------ + ---------  
  pg_toast.pg_toast_16874 | 89 GB  
  数00.warmstates | 1095 MB  
  ...  
(20行)

このTOASTテーブルは、ブロブされたデータの大きなレコードを保存する「timeseries」と呼ばれるテーブル用です。SUM(LENGTH(blob)/1024./1024.)timeseriesのすべてのレコードのA は、その列に最大16GBをもたらします。あってはならない理由は、そのままこのテーブルのTOASTテーブルが大きいようにする必要があります。

私はを実行しましたがVACUUM FULL VERBOSE ANALYZE timeseries、バキュームはエラーなしで完了まで実行されます。

情報: "pg_toast.pg_toast_16874"をバキュームします
情報: "pg_toast_16874":10448587ページで22483取り外し可能、10475318取り外し不可行バージョンが見つかりました
詳細:0デッド行バージョンはまだ削除できません。
削除できない行バージョンの範囲は、37〜2036バイトです。
20121422の未使用のアイテムポインターがありました。
合計空き容量(取り外し可能な行バージョンを含む)は0バイトです。4944885ページは空であるか、空になります。表の最後の0も含まれます。空きバイトが0の4944885ページは、移動先になる可能性があります。
CPU 75.31s / 29.59u秒経過877.79秒。
情報:インデックス "pg_toast_16874_index"に179931ページの10475318行バージョンが含まれるようになりました
詳細:23884インデックス行バージョンが削除されました。
101623インデックスページが削除されました。101623は現在再利用可能です。
CPU 1.35s / 2.46u秒経過21.07秒。

一部のスペース(約1GB)を解放したテーブルをREINDEXしました。プロセスにディスク上に十分なスペースがないため、テーブルをCLUSTERできません。同等のデータベースよりもはるかに大きい理由を知りたいので、テーブルを完全に再構築するのを待っています。

ここで PostgreSQL wikiからクエリを実行しました-"Show Database Bloat"、これは私が得るものです:

current_database | スキーマ名| テーブル名| tbloat | wastedbytes | いなめ| ibloat | 無駄なバイト  
----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + --------------  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | idx_timeseries_synchlevel | 0.0 | 0  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | idx_timeseries_localavail | 0.0 | 0  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | idx_timeseries_expirytime | 0.0 | 0  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | idx_timeseries_expiry_null | 0.0 | 0  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | uniq_localintid | 0.0 | 0  
ptrdb04 | 数00 | timeseries | 1.0 | 0 | pk_timeseries | 0.1 | 0  
ptrdb04 | 数00 | idx_timeseries_expiry_null | 0.6 | 0 | ?| 0.0 | 0

データベースはこの領域を「空」とはまったく見なしていないようですが、すべてのディスク領域がどこから来ているのかわかりません!

このデータベースサーバーは、他のデータサーバーから取得した同じレコードを保存するために、4〜5倍のディスク容量を使用することを決定していると思います。私の質問はこれです:行の物理ディスクサイズを確認する方法はありますか?このデータベースの1つの行のサイズを別の「正常な」データベースと比較したいと思います。

あなたが提供できる助けをありがとう!

アップデート1

サイズが原因で、ダンプされたスキーマからテーブルを再構築することになりました(別の日だけ放置することはできませんでした)。ソフトウェア同期プロセスを介してデータを同期した後、TOASTテーブルは約35GBでした。ただし、値の点で最も長いはずのblob列からの9GBまでしか説明できませんでした。他の26GBがどこから来ているのかわからない。CLUSTERed、VACUUM FULLed、およびREINDEXEDが使用できません。ローカルとリモートのデータサーバー間のpostgresql.confファイルはまったく同じです。このデータベースが各レコードをディスク上のより大きなスペースで保存しようとする理由はありますか?

更新2-修正済み

システムにPostgreSQL84パッケージを再インストールするまでも、データベースを最初から完全に再構築することにしました。データベースパスが再初期化され、テーブルスペースが完全に消去されました。サードパーティのソフトウェア同期プロセスによりテーブルが再作成され、最終的なサイズは最大12GBになりました。残念ながら、これは、問題の正確な原因が何であるかを解決するのに役立ちません。1〜2日見て、活性化されたデータベースがTOASTテーブルを処理する方法に大きな違いがあるかどうかを確認し、それらの結果をここに投稿します。

関係のサイズ


ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04->     pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04->   FROM pg_class C
ptrdb04->   LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04->   WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04->   ORDER BY pg_relation_size(C.oid) DESC
ptrdb04->   LIMIT 2;

        関係          |   サイズ   
 ------------------------- + --------- 
 pg_toast pg_toast_17269 | 18 GB 
 fews00 ウォームステート        | 1224 MB
 2   

VACUUM VERBOSE ANALYZE timeseries;

情報:「timeseries」:68382ページのうち58130ページで、取り外し可能な12699、取り外し不可能な681961行のバージョンが見つかりました
詳細:0デッド行バージョンはまだ削除できません。
未使用のアイテムポインターが105847個ありました。
0ページは完全に空です。
CPU 0.83s / 2.08u秒経過33.36秒
情報:「pg_toast.pg_toast_17269」をバキュームしています
情報:2055849行バージョンを削除するためにインデックス "pg_toast_17269_index"をスキャンしました
詳細:CPU 0.37s / 2.92u秒経過13.29秒
情報:「pg_toast_17269」:518543ページの2055849行バージョンを削除
詳細:CPU 8.60s / 3.21u秒経過358.42秒
情報:インデックス「pg_toast_17269_index」の36786ページに7346902行のバージョンが含まれるようになりました
詳細:2055849インデックス行バージョンが削除されました。
10410のインデックスページが削除され、5124は現在再利用可能です。
CPU 0.00s / 0.00u秒経過0.01秒。
情報:「pg_toast_17269」:2328079ページのうち1257871に、取り外し可能な1286128、取り外し不可能な行バージョン2993389が見つかりました
詳細:0デッド行バージョンはまだ削除できません。
未使用のアイテムポインタは18847個ありました。
0ページは完全に空です。
CPU 26.56s / 13.04u秒経過714.97秒
情報:「fews00.timeseries」を分析しています
情報: "timeseries":360192のライブ行と0のデッド行を含む68382ページのうち30000をスキャンしました。サンプルは30000行、推定合計行は1021022

(ディスク使用量を除いて)再構築後の唯一の顕著な違いは

情報:「pg_toast_17269」:取り外し可能な1286128、取り外し不可能な2993389行バージョンが見つかりました
@CraigRingerがコメントで述べたように。削除できない行数は、以前よりもはるかに少なくなっています。

新しい質問: 他のテーブルが別のテーブルのサイズに影響を与えることはありますか?(外部キーなどを介して)テーブルを再構築しても何も起こりませんでしたが、データベース全体を再構築すると問題が解決することが判明しました。


なぜ9.2に直接アップグレードしなかったのですか?真空領域では8.4よりもさらに改善されています(そして8.4はとにかく来年EOLになる予定です)
a_horse_with_no_name 2013

投稿を更新しました。アップグレードは当店ではなく、必ずしも私たちの要求によるものではありませんでした。残念ながら、9 +以上にアップグレードするオプションはありません。
BrM13 2013

OK。私はあなたが明白なものを見落とさないようにしたかっただけです;)
a_horse_with_no_name

回答:


9

この:

INFO: "pg_toast_16874": found 22483 removable, 10475318 nonremovable row versions in 10448587 pages 22483 removable, 10475318 nonremovable row versions in 10448587 pages

根本的な問題は、何かがそれらの行を「見る」ことができるため、削除できないことであると示唆しています。

その候補は次のとおりです。

  • 準備されたトランザクションを失った。チェックpg_catalog.pg_prepared_xacts; 空である必要があります。また、実行しSHOW max_prepared_transactionsます。ゼロを報告する必要があります。

  • オープンなアイドルトランザクションを使用した長時間実行セッション。PostgreSQL 8.4以降では、これはSERIALIZABLEトランザクションでのみ問題になります。セッションを確認pg_catalog.pg_stat_activity<IDLE> in transactionます。

ほとんどの場合、長いアイドル期間中にトランザクションのコミットまたはロールバックに失敗しているクライアントがあります。

これがそうでない場合は、次にチェックすることoctet_sizeは、対象のテーブルの各列の合計を行うことです。それをpg_relation_sizeテーブルとそのTOASTサイドテーブルのと比較してください。大きな違いがある場合、消費されたスペースはおそらく表示されていない行によるものであり、おそらくテーブルの膨張問題があります。それらが非常に類似している場合は、列ごとのオクテットサイズを合計し、上位の「n」値を取得するなどして、スペースの使用場所を絞り込みます。


1)pg_prepared_xactsとmax_prepared_transactionsは確かに空に戻りました。2)確かにいくつかのIDLEトランザクションがあり、そこからSELECT * FROM pg_stat_activity WHERE current_query LIKE '<IDLE>%';約30-40の結果が返されます。ただし、これはかなり正常なようです。私はいくつかの「正常な」サーバーをチェックしましたが、それらは同じでした。
BrM13 2013

3)これが私がしたことです。timeseries列をループし、octet_length(column)を引き出します。各値に行数を掛けて合計しました。timeseriesの場合、約430MB(pg_relation_sizeから493MB近く)とTOASTテーブル(列chunk_id、chunk_seq、chunk_dataを使用)用に438MBを取得しました。見積もりは正しいように見え、TOASTテーブルはrelation_sizeから約2桁ずれています(現在は60 GB)。膨らみがあるように見えますが、伝統的な種類(未使用の膨らみ)ではありません。それ以外の場合は、FULLVACが問題を処理する必要があります。
BrM13 2013

@Bradアイドルセッションは問題ありません。問題となっているのは、開いているトランザクションのあるアイドルセッション<IDLE> in transactionだけです。つまり、(a)しばらくアイドル状態であり、(b)SERIALIZABLE分離を使用しているか、8.3または古い。
クレイグリンガー2013

@Brad興味深いのは、TOASTテーブルだけが肥大化しているように見えることです。ところで、VACUUM FULL9.0より前のサーバーで多くを使用している場合は、それらのバージョンとREINDEX同じようにVACUUM FULLしたい場合、インデックスが大きく膨れる可能性があります。誰かFILLFACTORがトーストテーブルに不条理を設定したのではないかと思っていますが、10倍のスペース消費を超えてはいけません。
クレイグリンガー2013

IDLEの説明に感謝します。それがあなたの意味するところだと思ったのですが、確かに知っておくと良いでしょう。FILLFACTORに関しては、テーブルはデフォルトを使用しています。FYI- 8.4 CREATE TABLEドキュメントによるとデフォルトは100であり、TOASTテーブルにFILLFACTORを設定することはできません
BrM13 2013

0

なぜ肥大化しているのか、私には何の洞察もありません。しかし、私はいくつかの検索を行い、おそらくこのリンクにはいくつかの洞察があります:http : //postgresql.1045698.n5.nabble.com/A-154-GB-table-swelled-to-527-GB-on-the-Slony-slave -How-to-compact-it-td5543034.html ...これは正確な状況ではありませんが、おそらくファントムブロートの底に到達するのに十分なほど近いでしょう。

ただし、この時点でテーブルを圧縮する唯一の方法は、CLUSTERすることです。ディスク容量が少ないので、それは問題です。

これについての私の提案は次のとおりです。別のドライブに多くの余分なスペースがあるテーブルスペースを作成し、問題のテーブルをそのテーブルスペースに割り当てます。PostgreSQLはテーブルを新しいテーブルスペースにコピーします(おそらくプロセス中にテーブルをロックするため、メンテナンスウィンドウが必要になります)。次に、テーブルをVACFULLします(デフォルトのテーブルスペース内のテーブルによって消費された古いスペースのほとんどをクリアします)。次に、テーブルをクラスタ化すると、テーブル自体が圧縮されます。次に、それをデフォルトのテーブルスペースに戻し、VACFULLを再度実行します(新しいテーブルスペースの未使用スペースをクリアするため)。


実際には、テーブルを再構築し(スキーマをダンプしてそこから再構築し)、リモートデータベースの1つから直接データをプルしました。プロセスが完了した後も、データベースは依然として35GBであり、「ワイド」ブロブ列が占めるのは9GBだけでした。CLUSTERed、VACUUM FULLed、REINDEXed、そして私はまだたくさんの不可思議なディスク使用状況に座っています。
BrM13 2013

リンクが死んでいる:(
hayd '8/8
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.