2012-12-18 19 views
7

数百のクライアントに配備されたPostgreSQLデータベースサーバを使用する製品があります。そのうちのいくつかは数十ギガバイトのデータを集めています。したがって、次のバージョンでは、徐々にアーカイブする自動クリーンアップ手順を紹介し、夜間バッチジョブ中にDELETE古いレコードを導入します。PostgresQL膨大なテーブル用にVACUUM FULLを自動化

私が正しく理解していれば、autovacuumはタプルを分析して再構成するので、少ないレコードが存在したときと同じパフォーマンスになります。私が正しく理解していればそれだけ FULL VACUUMで発生し、そしてそれは自動バキュームによってトリガされていないので、

実際のディスク・スペースは、解放されません。

私はこれを行う自動化プロセスについて考えていました。

nagios check_postgresで使用されているbloat viewがhttp://wiki.postgresql.org/wiki/Show_database_bloatにあります。

このビューは適切ですか? tbloatが> 2の場合、VACUUM FULLを使用する可能性があることを理解していますか? ibloatが高すぎる場合は、REINDEXを使用できますか?

毎日のバッチジョブとして実行する次のジョブについてのコメントはありますか?もちろんオフ解析専用

  • select tablename from bloatview order by tbloat desc limit 1
  • vacuumdb -f -t tablename mydatabase
  • select tablename, iname from bloatview order by ibloat desc limit 1
  • reindexdb -t tablename -i iname mydatabase
    • vacuumdb -Z mydatabase #vacuumは、私はまだ素敵なperlスクリプト内でそれをラップする必要がありますcrontab(私たちはubuntu 12を使っています)、あるいはpostgresqlに何らかの並べ替えがありますスケジューラの私はこれを行うことができますか?

      この合計超過分は、はるかに簡単な手順がありますか?

    +0

    vacuumdb -Zはおそらく必要ありませんが、自動バキュームは分析を最新の状態に保つのに非常に有効です。 – greyfairer

    答えて

    4

    あなたはおそらくドン」それが必要です。これを一度行うのは良いことです。最初のアーカイブ作業後にディスクスペースを元に戻しますが、それ以降は毎日のアーカイブ作業と自動バキュームが、死んだタプルの膨張を防ぎます。

    vacuum fullの代わりに、cluster table_name using index_name; analyze table_nameを実行することもよくあります。これにより、インデックスに従って行が並べ替えられます。このように、関連するテーブル行をディスク上に物理的に閉じて保存することができます。ディスクのシークは制限されます(従来のディスクドライブでは重要でSSDではほとんど関係ありません)。

    そして、vacuum fullclusterの両方が、実行中にテーブルを使用できなくすることに注意してください。

    +0

    ヒントをありがとう。導入されたクリーンアッププロセスは、夜間に数時間実行される予定ですが、終了する前にいくつかのクライアントで数日間かかるでしょう。クリーンアップが完全に終了するまで待ってから、スケジュールされたダウンタイム中に一度だけフルまたはクラスタを実行してください。 これをスケジュールするのに必要なインストールは200種類しかないので、そのためにいくつかの自動化が必要です。 CLUSTERのヒントをありがとう。 – greyfairer

    +0

    PostgreSQL 9.0以降では、「VACUUM FULL」の最適化により、これを行う適切な方法になりました。 (https://wiki.postgresql.org/wiki/VACUUM_FULL#CLUSTERを参照) –

    3

    OK、私はそれを通り抜けました。

    私は、次の2つにそれを分割するビューを再加工/簡素化:

    CREATE OR REPLACE VIEW 
        bloat_datawidth AS 
    SELECT 
        ns.nspname AS schemaname, 
        tbl.oid AS relid, 
        tbl.relname, 
        CASE 
         WHEN every(avg_width IS NOT NULL) 
         THEN SUM((1-null_frac)*avg_width) + MAX(null_frac) * 24 
         ELSE NULL 
        END AS datawidth 
    FROM 
        pg_attribute att 
    JOIN 
        pg_class tbl 
    ON 
        att.attrelid = tbl.oid 
    JOIN 
        pg_namespace ns 
    ON 
        ns.oid = tbl.relnamespace 
    LEFT JOIN 
        pg_stats s 
    ON 
        s.schemaname=ns.nspname 
    AND s.tablename = tbl.relname 
    AND s.inherited=false 
    AND s.attname=att.attname 
    WHERE 
        att.attnum > 0 
    AND tbl.relkind='r' 
    GROUP BY 
        1,2,3; 
    

    そして

    CREATE OR REPLACE VIEW 
        bloat_tables AS 
    SELECT 
        bdw.schemaname, 
        bdw.relname, 
        bdw.datawidth, 
        cc.reltuples::bigint, 
        cc.relpages::bigint, 
        ceil(cc.reltuples*bdw.datawidth/current_setting('block_size')::NUMERIC)::bigint AS expectedpages, 
        100 - (cc.reltuples*100*bdw.datawidth)/(current_setting('block_size')::NUMERIC*cc.relpages) AS bloatpct 
    FROM 
        bloat_datawidth bdw 
    JOIN 
        pg_class cc 
    ON 
        cc.oid = bdw.relid 
    AND cc.relpages > 1 
    AND bdw.datawidth IS NOT NULL; 
    

    そして、cronジョブ:

    #!/bin/bash 
    
    MIN_BLOAT=65 
    MIN_WASTED_PAGES=100 
    LOG_FILE=/var/log/postgresql/bloat.log 
    DATABASE=unity-stationmaster 
    SCHEMA=public 
    
    if [[ "$(id -un)" != "postgres" ]] 
    then 
    echo "You need to be user postgres to run this script." 
    exit 1 
    fi 
    
    TABLENAME=`psql $DATABASE -t -A -c "select relname from bloat_tables where bloatpct > $MIN_BLOAT and relpages-expectedpages > $MIN_WASTED_PAGES and schemaname ='$SCHEMA' order by wastedpages desc limit 1"` 
    
    if [[ -z "$TABLENAME" ]] 
    then 
    echo "No bloated tables." >> $LOG_FILE 
    exit 0 
    fi 
    
    vacuumdb -v -f -t $TABLENAME $DATABASE >> $LOG_FILE 
    
    関連する問題