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

PostgreSQL:6つのそれほど簡単ではない部分

    PostgreSQLには、オープンソースのRDBMSスペースでは比類のない優れた機能セットが付属しています。特にアプリケーション開発者にとっては、ほとんどの場合、習得と使用が簡単です。ただし、一部の部分は、まあ、単純に簡単ではありません。セットアップと設定を正しく行うには作業が必要であり、通常はミッションクリティカルでもあります。

    接続管理

    PostgreSQLはバックエンドプロセスと呼ばれる新しいプロセスを起動します 、各接続を処理します。これは、他の同等のサーバーソフトウェアに見られる最新のイベントループ/スレッドプールベースの接続処理アーキテクチャとは対照的です。完全なプロセスを生成するには、より多くの時間とリソースが必要であり、接続が高速で開閉されるアプリケーションでは、クエリの待ち時間が長くなります。

    >

    ほとんどの展開では、接続のプールがある程度必要です。アプリケーションレベルでは、これはプログラミング言語/ライブラリ機能を使用できます。たとえば、sql / DB.SetMaxIdleConnscanを使用して、単一のGoアプリケーション内からの接続の再利用を増やすことができます。

    ただし、多くの場合、サードパーティの接続プールまたは負荷分散ソリューションを使用する必要があります。接続プーラーは、上流のPostgresサーバーへのアイドル接続のプールを維持します。これらの接続は、着信クライアント接続に割り当てられ、プロキシされます。通常、クライアントから送信されたSQLを解析して、トランザクション境界とデータ変更DMLを認識し、トランザクションレベルの接続プールやレプリカの読み取りなどの機能を実装します。

    PgBouncerは、人気のある軽量のシングルバイナリ接続プーラーであり、同じシステム内でPostgreSQLと一緒に実行されることがよくあります。

    PgPoolは、PgBouncerよりも用途が広いです。たとえば、負荷分散やレプリケーションも実行できます。

    ただし、接続プールには独自の問題があります。まず、展開で維持されているのは追加の可動部分です。異なるクレデンシャルまたは認証メカニズムを使用するクライアントがある場合、認証の設定も面倒です。LISTEN/ NOTIFY、プリペアドステートメント、一時テーブルなどの一部の接続レベルの機能では、機能するために追加の構成またはクライアント側の変更が必要になる場合があります。

    ダウンタイムゼロのアップグレード

    マイナーバージョン(13.x-> 13.y)間でPostgreSQLをアップグレードするには、新しいパッケージをインストールしてサーバープロセスを再起動する必要があります。サーバープロセスを再起動すると、接続されているすべてのクライアントが必然的に中断されますが、ダウンタイムはサービスの再起動の期間に限定されるため、それでも合理的な質問です。

    ただし、メジャー(12.x-> 13.y)バージョン間のアップグレードは、はるかに大きな問題です。通常、データが多いほど、プロセスはより苦痛になります。

    少量のデータ(たとえば数十GB)でのみ機能する最も簡単な方法は、古いバージョンからデータをダンプして新しいバージョンのサーバーに復元することです。別のオプションは、オーケストレーションされたダンスを必要とするpg_upgradeを使用することです。両方のバージョンのPostgresのバイナリを含みます。

    いずれの場合も、データベースはかなりの時間ダウンします。

    理想的には、新しいバージョンのサーバーに複製し、新しいバージョンのサーバーをプライマリとして昇格させることが可能である必要があります。ただし、メジャーバージョンが異なるスタンバイサーバーにストリーミングレプリケーションを実行することはできません。論理レプリケーションは、ジョブに適しているように見えますが、完全なレプリケーションを確実にするために回避する必要のある特定の落とし穴があります。

    PostgresのほとんどのHAソリューションはストリーミングレプリケーションに依存しているため、クラスター内のノードを一度に1つずつアップグレードすることはできません。

    現在の最先端技術は、論理レプリケーションの制限を回避しながら、論理レプリケーションを使用することであり、アップグレードフェーズ中にアプリケーションが使用できる機能(DDLなど)を制限することも含まれる可能性があります。

    高可用性

    PostgreSQLには、HAソリューションの構築に必要なすべての低レベル機能が付属しています。フィードバック付きレプリケーション、カスケードレプリケーション、同期レプリケーション、スタンバイ、ホットスタンバイ、スタンバイプロモーションなどです。ただし、実際には、箱から出してすぐにHAソリューションを提供します。ヘルスを監視し、スタンバイに自動的にフェイルオーバーするためのフレームワークやツールはありません。マルチノードHAクラスターの概念はありません。

    高可用性のPostgresデプロイメントを作成するには、サードパーティのソリューションをセットアップして実行する必要があります。現在のお気に入りはpg_auto_failoverとPatroniです。 Patroniは、ZooKeeperやetcdなどの既存の高可用性構成ストアに依存していますが、pg_auto_failoverはそれがなくても実行できます。

    これらのいずれかを本番環境で評価、展開、およびテストするには、時間と労力がかかります。監視、警告、運用のプレイブックを設定して維持する必要があります。

    膨張管理

    PostgreSQLのMVCCアーキテクチャは、データが上書きされないことを意味します。行を変更すると、新しいバージョンの行がディスクに書き出されるだけです。行を削除するということは、その行がfuturetransactionsから見えないことを記録することだけを意味します。行バージョンが進行中または将来のトランザクションからアクセスできない場合、それはもはや使用されなくなり、「膨張」と呼ばれます。この膨張をガベージコレクションするプロセスは「バキューム」と呼ばれます。

    膨張はアプリケーションからは見えず、DBAの頭痛の種になります。更新が多いテーブルの場合、膨張の監視と管理は重要な問題です。自動真空プロセスは大いに役立ちますが、そのしきい値はグローバルまたはごとに調整する必要がある場合があります。テーブルサイズが管理できないほど大きくならないようにするためのテーブルレベル。

    インデックスも肥大化の影響を受け、autovacuumはここでは役に立ちません。行の削除とインデックス付き列の更新により、インデックスのエントリが無効になります。インデックス付きの列への更新を伴う更新の重い作業負荷は、絶えず増大し、非効率的なインデックスにつながる可能性があります。インデックスにはバキュームに相当するものはありません。唯一の解決策は、REINDEXを使用してインデックス全体を再構築するか、テーブルでVACUUMFULLを使用することです。

    テーブルごとに1つの値(pg_stat_all_tables.n_dead_tup)を除いて、Postgresはテーブルの肥大化を推定する方法を何も提供せず、インデックスについては何も提供しません。最も実用的な方法は、check_postgresから恐ろしいクエリを実行することです。

    pgmetricsはcheck_postgresからのクエリを組み込み、すべてのテーブルとインデックスのサイズと膨張情報を含むJSONおよびCSV形式の出力を生成できます。監視ツールや自動化ツールに入力できます。

    pg_repackは、VACUUM FULLの一般的な代替手段です。同じジョブを実行できますが、ロックはありません。定期的にVACUUMFULLを実行する必要がある場合は、調査が必要なツールです。

    zheapは、何年にもわたって開発されてきたPostgresの新しいストレージエンジンであり、インプレース更新によって膨張を減らすことを約束します。

    クエリプラン管理

    Core PostgreSQLは、この分野で2つの基本的なツールのみを提供します。

    • pg_stat_statements クエリ分析の拡張機能–これにより、クエリの計画と実行時間、ディスクとメモリの使用量の合計と平均が得られます
    • auto_explain 拡張機能。クエリ実行計画をPostgresログの宛先に出力できます

    pg_stat_statementsによって提供される統計情報は、 auto_explain を使用して、十分に処理できます。 計画をログファイルに強制し、計画の履歴、ベースライン、および管理機能を提供するPostgresの商用競合他社と比較して、実際にはハックにすぎないようにそれらを抽出します。

    Postgresの現在の最先端技術は、クエリプランのログファイルをマイニングし、それらを他の場所に保存することです。しかし、おそらく最もハンディキャップの問題は、クエリプランをpg_stat_statementsの対応する分析に関連付けることができないことです。 pgDashがこれを行う方法は、pg_stat_statementsとauto_explain出力の両方のSQLクエリテキストを解析し、pg_stat_statementsによって行われるマングリングを調整して、2つを一致させようとすることです。完全なPostgreSQL方言SQLパーサーが必要です。

    現在、コアPostgreSQLでは、ベースライン設定、プラン選択のポリシー設定などは不可能です。

    基本的にpg_stat_statementsの改良版である拡張機能がいくつかありますが、サードパーティの拡張機能の使用に伴う追加の手順により、ほとんどの人にとって、特にマネージドPostgresプロバイダーを使用している場合は困難になります。

    チューニング

    PostgreSQLには、under-configured-by-defaultshared_bufferssettingから始まる、多数のチューニングオプションがあります。さまざまな操作(max_worker_processes、max_parallel_ *など)の並列ワーカーの数など、理解と設定が簡単なものもあります。他の領域は少しあいまいですが(wal_compression、random_page_costなど)、一般的には有益です。ただし、最も厄介なのは、ワークロードに関する定量化可能な情報を必要とするものです。

    たとえば、 work_mem が低すぎる場合、クエリは一時ディスクファイルを使用する可能性があります。高すぎる場合、および十分な同時クエリがある場合、PostgresバックエンドプロセスはOOM-killされる可能性があります。では、どの番号に設定するかをどのように判断しますか?

    実際には、特にOLTPワークロードとWebアプリケーションワークロードでは、クエリのピークメモリ需要を予測することは不可能です。最善の策は、適切な値を設定してから、クエリを監視して、work_memの値を高くすることでメリットが得られたかどうかを確認することです。

    そして、どのようにそれをしますか?拡張子を取得する必要がありますauto_explain 各クエリのクエリ実行プランをログに記録するには、Postgresのログファイルからクエリ実行プランを抽出し、各クエリプランを調べて、ディスクベースの外部マージまたは損失のあるヒープブロックを含むビットマップヒープスキャンを使用しているかどうかを確認します。

    不可能ではありません、ただ難しいです。


    1. ミリ秒単位のCURRENT_TIMESTAMP

    2. psqlでデータベースを切り替える方法は?

    3. PostgreSQLリストビュー

    4. MySQL ABS()関数–数値の絶対値を返します