sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLVACUUMおよびANALYZEのベストプラクティスのヒント

    VACUUMとANALYZEは、PostgreSQLデータベースの2つの最も重要なメンテナンス操作です。

    テーブル内の「デッドタプル」が占めるスペースを回復するために、バキュームが使用されます。レコードが削除または更新されると(削除の後に挿入が続く)、デッドタプルが作成されます。 PostgreSQLはテーブルから古い行を物理的に削除しませんが、クエリがその行を返さないように「マーカー」を配置します。真空プロセスが実行されると、これらの死んだタプルが占めるスペースは、他のタプルによって再利用可能としてマークされます。

    「分析」操作は、その名前が示すとおりに実行されます。データベースのテーブルの内容を分析し、すべてのテーブルの各列の値の分布に関する統計を収集します。 PostgreSQLクエリエンジンはこれらの統計を使用して、最適なクエリプランを見つけます。データベースで行が挿入、削除、および更新されると、列の統計も変更されます。 ANALYZE – DBAによって手動で実行されるか、自動バキューム後にPostgreSQLによって自動的に実行されます–統計が最新であることを確認します。

    それらは比較的単純に聞こえますが、舞台裏、バキューム、および分析は2つの複雑なプロセスです。幸い、DBAは内部についてあまり心配する必要はありません。ただし、これらのプロセスを手動で実行したり、構成パラメーターの最適値を設定したりすることについて、混乱することがよくあります。

    この記事では、VACUUMとANALYZEのいくつかのベストプラクティスを共有します。

    ヒント1:理由なしに手動VACUUMまたはANALYZEを実行しないでください

    PostgreSQLバキューム(自動バキュームまたは手動バキューム)は、テーブルの肥大化を最小限に抑え、トランザクションIDのラップアラウンドを防ぎます。 Autovacuumは、デッドタプルによって占有されているディスクスペースを回復しません。ただし、 VACUUM FULLを実行する コマンドはそうします。ただし、VACUUMFULLにはパフォーマンスへの影響があります。ターゲットテーブルは操作中は排他的にロックされ、テーブルの読み取りさえも防止します。このプロセスでは、テーブルの完全なコピーも作成されます。これには、実行時に追加のディスク領域が必要です。膨張の割合が非常に高く、クエリがひどく苦しんでいる場合を除いて、VACUUMFULLを実行しないことをお勧めします。また、データベースアクティビティが最も少ない期間を使用することをお勧めします。

    また、データベース全体で手動バキュームを頻繁に実行しないこともベストプラクティスです。ターゲットデータベースは、自動バキュームプロセスによってすでに最適にバキュームされている可能性があります。その結果、手動バキュームはデッドタプルを削除しない可能性がありますが、不要なI/O負荷またはCPUスパイクを引き起こす可能性があります。必要に応じて、手動バキュームは、ライブ行とデッド行の比率が低い、自動バキューム間のギャップが大きいなど、必要な場合にのみテーブルごとに実行する必要があります。また、ユーザーアクティビティが最小限の場合は、手動掃除機を実行する必要があります。

    Autovacuumは、テーブルのデータ分散統計を最新の状態に保ちます(再構築しません)。手動で実行する場合、分析 コマンドは、これらの統計を更新するのではなく、実際に再構築します。繰り返しになりますが、定期的な自動バキュームによって統計がすでに最適に更新されているときに統計を再構築すると、システムリソースに不必要な圧力がかかる可能性があります。

    ANALYZEを手動で実行する必要があるのは、ターゲットテーブルにデータを一括ロードした直後です。既存のテーブルに多数(数百)の新しい行があると、列のデータ分布が大幅に歪められます。新しい行により、既存の列の統計が古くなります。クエリオプティマイザがそのような統計を使用する場合、クエリのパフォーマンスは非常に遅くなる可能性があります。このような場合、データのロード直後にANALYZEコマンドを実行して統計を完全に再構築する方が、自動バキュームが開始されるのを待つよりも優れたオプションです。

    ヒント2:自動真空しきい値を微調整する

    postgresql.conf で自動バキュームを確認または調整し、構成パラメータを分析することが不可欠です。 ファイルまたは個々のテーブルのプロパティで、自動真空とパフォーマンスの向上のバランスを取ります。

    PostgreSQLは、2つの構成パラメーターを使用して、自動真空を開始するタイミングを決定します。

    • autovacuum_vacuum_threshold :これのデフォルト値は50です
    • autovacuum_vacuum_scale_factor :これのデフォルト値は0.2です

    同時に、これらのパラメーターは、テーブル内のデッド行の数がそのテーブル内の行数にスケールファクターとバキュームしきい値を掛けた数を超えたときに自動バキュームを開始するようにPostgreSQLに指示します。つまり、PostgreSQLは次の場合にテーブルで自動バキュームを開始します。

    pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor)  + autovacuum_vacuum_threshold

    中小規模のテーブルの場合、これで十分な場合があります。たとえば、10,000行のテーブルでは、自動バキュームが開始される前に、デッド行の数が2,050((10,000 x 0.2)+ 50)を超えている必要があります。

    データベース内のすべてのテーブルで同じ速度のデータ変更が行われるわけではありません。通常、いくつかの大きなテーブルではデータが頻繁に変更されるため、デッド行の数が多くなります。このようなテーブルでは、デフォルト値が機能しない場合があります。たとえば、デフォルト値では、100万行のテーブルには、自動バキュームが開始する前に200,050を超えるデッド行が必要になります((1000,000 x 0.2)+ 50)。これは、自動バキューム間のギャップが長くなり、自動バキューム時間が長くなり、さらに悪いことに、テーブル上のアクティブなトランザクションが自動バキュームをロックしている場合、自動バキュームがまったく実行されないことを意味します。

    したがって、目標は、これらのしきい値を最適な値に設定して、自動バキュームが定期的に発生し、デッド行の数を比較的少なく保ちながら、長い時間(およびユーザーセッションに影響を与える)しないようにすることです。

    1つのアプローチは、いずれかのパラメーターを使用することです。したがって、autovacuum_vacuum_scale_factorを0に設定し、代わりにautovacuum_vacuum_thresholdを5,000に設定すると、デッド行の数が5,000を超えると、テーブルは自動バキュームされます。

    ヒント3:自動分析のしきい値を微調整する

    autovacuumと同様に、autoanalyzeも、autovacuumが自動分析をトリガーするタイミングを決定する2つのパラメーターを使用します。

    • autovacuum_analyze_threshold :これのデフォルト値は50です
    • autovacuum_analyze_scale_factor :これのデフォルト値は0.1です

    autovacuumと同様に、autovacuum_analyze_thresholdパラメーターは、自動分析が開始される前に、テーブル内の挿入、削除、または更新されたタプルの数を指定する値に設定できます。このパラメータは、大規模なテーブルとトランザクションの多いテーブルで別々に設定することをお勧めします。テーブル構成はpostgresql.conf値をオーバーライドします。

    以下のコードスニペットは、テーブルのautovacuum_analyze_threshold設定を変更するためのSQL構文を示しています。

    ALTER TABLE <table_name> 
    SET (autovacuum_analyze_threshold = <threshold rows>)

    ヒント4:自動真空ワーカーを微調整する

    DBAが見落としがちなもう1つのパラメータは、 autovacuum_max_workersです。 、デフォルト値は3です。自動バキュームは単一のプロセスではなく、並行して実行される多数の個別のバキュームスレッドです。複数のワーカーを指定する理由は、大きなテーブルのバキュームが小さなテーブルとユーザーセッションのバキュームを妨げないようにするためです。 autovacuum_max_workersパラメーターは、クリーンアップを実行するためにautovacuumワーカースレッドの数をスピンアップするようにPostgreSQLに指示します。

    PostgreSQL DBAの一般的な方法は、自動バキュームを高速化することを期待して、最大ワーカースレッドの数を増やすことです。すべてのスレッドが同じautovacuum_vacuum_cost_limitを共有しているため、これは機能しません。 、デフォルト値は200です。各自動真空スレッドには、以下に示す次の式を使用してコスト制限が割り当てられます。

    individual thread’s cost_limit = autovacuum_vacuum_cost_limit / autovacuum_max_workers

    自動真空スレッドによって行われる作業のコストは、次の3つのパラメーターを使用して計算されます。

    • vakuum_cost_page_hit :これのデフォルト値は1です
    • vakuum_cost_page_miss :これのデフォルト値は10です
    • vakuum_cost_page_dirty :これのデフォルト値は20です

    これらのパラメータの意味は次のとおりです:

    • バキュームスレッドが共有バッファでクリーンアップすることになっているデータページを見つけた場合、コストは1です。
    • データページが共有バッファになく、OSキャッシュにある場合、コストは10になります。
    • バキュームスレッドがデッドローを削除する必要があるためにページをダーティとマークする必要がある場合、コストは20になります。

    ワーカースレッドの数を増やすと、各スレッドのコスト制限が低くなります。各スレッドにはより低いコスト制限が割り当てられているため、コストのしきい値に簡単に到達すると、スレッドはより頻繁にスリープ状態になり、最終的にはバキュームプロセス全体の実行が遅くなります。 autovacuum_vacuum_cost_limitを2000などのより高い値に増やしてから、ワーカースレッドの最大数を調整することをお勧めします。

    より良い方法は、必要な場合にのみ、個々のテーブルに対してこれらのパラメーターを調整することです。たとえば、大きなトランザクションテーブルの自動バキュームに時間がかかりすぎる場合、テーブルは、独自のバキュームコスト制限とコスト遅延を使用するように一時的に構成されている可能性があります。コスト制限と遅延は、postgresql.confで設定されたシステム全体の値を上書きします。

    以下のコードスニペットは、個々のテーブルを構成する方法を示しています。

    ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_limit = <large_value>)
    ALTER TABLE <table_name> SET (autovacuum_vacuum_cost_delay = <lower_cost_delay>)

    最初のパラメーターを使用すると、テーブルに割り当てられた自動バキュームスレッドが、スリープ状態になる前により多くの作業を実行するようになります。 autovacuum_vacuum_cost_delayを下げる また、スレッドのスリープ時間が短くなることも意味します。

    最終的な考え

    ご覧のとおり、真空と分析の構成パラメーターの変更は簡単ですが、最初に注意深く観察する必要があります。すべてのデータベースは、そのサイズ、トラフィックパターン、およびトランザクションの速度の点で異なります。 DBAは、パラメータを変更したり、手動のバキューム/分析体制を展開したりする前に、データベースに関する十分な情報を収集することから始めることをお勧めします。そのような情報は次のようになります:

    • 各テーブルの行数
    • 各テーブルのデッドタプルの数
    • 各テーブルの最後の掃除機の時間
    • 各テーブルの最後の分析時刻
    • 各テーブルでのデータの挿入/更新/削除の割合
    • 各テーブルの自動バキュームにかかる時間
    • テーブルがバキュームされていないことに関する警告
    • 最も重要なクエリとそれらがアクセスするテーブルの現在のパフォーマンス
    • 手動のバキューム/分析後の同じクエリのパフォーマンス

    ここから、DBAはいくつかの「パイロット」テーブルを選択して最適化を開始できます。テーブルのバキューム/分析プロパティの変更を開始し、パフォーマンスを確認できます。 PostgreSQLはスマートデータベースエンジンです。DBAは、手動で行うよりもPostgreSQLにバキュームと分析を行わせるのがおそらく最善であると考えるでしょう。


    1. 例を使用したSQLiteLike()関数

    2. PostgreSQLでテーブルのリスト列名とデータ型を取得するにはどうすればよいですか?

    3. 社会的距離を保ちながらチームを管理するための5つのヒント

    4. MariaDB JSON_TABLE()の説明