PostgreSQLのメモリ管理は、データベースサーバーのパフォーマンスを向上させるために重要です。 PostgreSQL構成ファイル(postgres.conf)は、データベースサーバーの構成を管理します。パラメータのデフォルト値を使用しますが、ワークロードと動作環境をより適切に反映するようにこれらの値を変更できます。
このブログでは、これらのメモリ関連のパラメータについて説明します。ただし、始める前に、PostgreSQLのメモリアーキテクチャを見てみましょう。
メモリアーキテクチャ
PostgreSQLのメモリは、次の2つのカテゴリに分類できます。
- ローカルメモリ領域:各バックエンドプロセスによって、独自に使用するために割り当てられます。
- 共有メモリ領域:PostgreSQLサーバーのすべてのプロセスで使用されます。
ローカルメモリエリア
PostgreSQLでは、各バックエンドプロセスがクエリ処理用にローカルメモリを割り当てます。各エリアは、サイズが固定または可変のサブエリアに分割されます。
サブエリアは以下の通りです。
Work_mem
エグゼキュータは、この領域を使用して、ORDERBYおよびDISTINCT操作によってタプルをソートします。また、マージ結合およびハッシュ結合操作によるテーブルの結合にも使用されます。
Maintenance_work_mem
このパラメーターは、特定の種類の保守操作(VACUUM、REINDEX)に使用されます。
Temp_buffers
エグゼキュータはこの領域を使用して一時テーブルを保存します。
共有メモリ領域
共有メモリ領域は、PostgreSQLサーバーの起動時に割り当てられます。このエリアは、いくつかの固定サイズのサブエリアに分割されています。
共有バッファプール
PostgreSQLは、テーブルとインデックス内のページを永続ストレージから共有バッファプールにロードし、それらを直接操作します。
WALバッファー
PostgreSQLはWAL(ログ先行書き込み)メカニズムをサポートしており、サーバーの障害後にデータが失われないようにします。 WALデータは実際にはPostgreSQLのトランザクションログであり、WALバッファは永続ストレージに書き込む前のWALデータのバッファリング領域です。
コミットログ
コミットログ(CLOG)は、すべてのトランザクションの状態を保持し、同時実行制御メカニズムの一部です。コミットログは共有メモリに割り当てられ、トランザクション処理全体で使用されます。
PostgreSQLは次の4つのトランザクション状態を定義します。
- IN_PROGRESS
- コミット済み
- 中止
- サブコミット
PostgreSQLメモリパラメータの調整
PostgreSQLのメモリ管理に推奨されるいくつかの重要なパラメータがあります。次の点を考慮に入れる必要があります。
Shared_buffers
このパラメーターは、共有メモリー・バッファーに使用されるメモリーの量を指定します。 shared_buffersパラメーターは、データをキャッシュするためにサーバー専用のメモリー量を決定します。 shared_buffersのデフォルト値は通常128メガバイト(128MB)です。
古いSolarisバージョンやSGIなどの一部のプラットフォームでは、値が大きいとカーネルの再コンパイルなどの侵襲的なアクションが必要になるため、このパラメーターのデフォルト値は非常に低くなっています。最新のLinuxシステムでも、カーネルは、最初にカーネル設定を調整しない限り、shared_buffersを32MB以上に設定できない可能性があります。
PostgreSQL 9.4以降ではメカニズムが変更されているため、カーネル設定をそこで調整する必要はありません。
データベースサーバーの負荷が高い場合は、高い値を設定するとパフォーマンスが向上します。
1GB以上のRAMを搭載した専用DBサーバーがある場合、shared_buffer構成パラメーターの妥当な開始値は、システムのメモリーの25%です。
shared_buffersのデフォルト値=128MB。変更するには、PostgreSQLサーバーを再起動する必要があります。
shared_buffersを設定するための一般的な推奨事項は次のとおりです。
- 2 GB未満のメモリでは、shared_buffersの値をシステムメモリ全体の20%に設定します。
- 32 GB未満のメモリで、shared_buffersの値をシステムメモリ全体の25%に設定します。
- 32GBのメモリを超える場合は、shared_buffersの値を8GBに設定します
Work_mem
このパラメーターは、一時ディスクファイルに書き込む前に内部ソート操作とハッシュテーブルによって使用されるメモリの量を指定します。多くの複雑な並べ替えが行われていて、十分なメモリがある場合は、work_memパラメータを増やすと、PostgreSQLがより大きなメモリ内並べ替えを実行できるようになり、ディスクベースの同等のものよりも高速になります。
複雑なクエリの場合、多くの並べ替えまたはハッシュ操作が並行して実行される可能性があることに注意してください。各操作は、一時ファイルへのデータの書き込みを開始する前に、この値が指定するのと同じ量のメモリを使用できます。複数のセッションがそのような操作を同時に実行している可能性が1つあります。したがって、使用される合計メモリは、work_memパラメータの値の何倍にもなる可能性があります。
適切な値を選択するときは、それを覚えておいてください。ソート操作は、ORDER BY、DISTINCT、およびマージ結合に使用されます。ハッシュテーブルは、ハッシュ結合、INサブクエリのハッシュベースの処理、およびハッシュベースの集計で使用されます。
パラメータlog_temp_filesを使用して、ソート、ハッシュ、および一時ファイルをログに記録できます。これは、ソートがメモリに収まらずにディスクに流出しているかどうかを判断するのに役立ちます。 EXPLAIN ANALYZEプランを使用して、ディスクに流出する種類を確認できます。たとえば、EXPLAIN ANALYZEの出力で、次のような行が表示された場合:「並べ替え方法:外部マージディスク:7528kB 」、少なくとも8MBのwork_memは、中間データをメモリに保持し、クエリの応答時間を改善します。
work_memのデフォルト値=4MB。
work_memを設定するための一般的な推奨事項は次のとおりです。
- 低い値から開始:32〜64MB
- 次に、ログで「一時ファイル」の行を探します
- 最大の一時ファイルの2〜3倍に設定
メンテナンス_work_mem
このパラメーターは、VACUUM、CREATE INDEX、ALTER TABLE ADDFOREIGNKEYなどの保守操作で使用されるメモリーの最大量を指定します。データベースセッションで一度に実行できる操作は1つだけであり、PostgreSQLインストールではそれらの多くが同時に実行されないため、maintenance_work_memの値をwork_memよりも大幅に大きく設定しても安全です。
値を大きく設定すると、データベースダンプのバキュームと復元のパフォーマンスが向上する可能性があります。
autovacuumの実行時には、autovacuum_max_workers倍までこのメモリが割り当てられる可能性があることを覚えておく必要があります。したがって、デフォルト値を高く設定しすぎないように注意してください。
Maintenance_work_memのデフォルト値=64MB。
Maintenance_work_memを設定するための一般的な推奨事項は次のとおりです。
- システムメモリの10%、最大1GBの値を設定します
- VACUUMに問題がある場合は、さらに高く設定できるかもしれません
Effective_cache_size
Effective_cache_sizeは、オペレーティングシステムおよびデータベース自体の内部でディスクキャッシングに使用できるメモリの見積もりに設定する必要があります。これは、割り当てではなく、オペレーティングシステムとPostgreSQLバッファキャッシュで使用できると予想されるメモリの量に関するガイドラインです。
PostgreSQLクエリプランナーはこの値を使用して、検討しているプランがRAMに収まると予想されるかどうかを判断します。設定が低すぎると、期待どおりにクエリを実行するためにインデックスが使用されない場合があります。ほとんどのUnixシステムはキャッシュ時にかなり積極的であるため、専用データベースサーバーで使用可能なRAMの少なくとも50%がキャッシュされたデータでいっぱいになります。
Effective_cache_sizeの一般的な推奨事項は次のとおりです。
- 値を使用可能なファイルシステムキャッシュの量に設定します
- わからない場合は、値をシステムメモリ全体の50%に設定してください
実効キャッシュサイズのデフォルト値=4GB。
Temp_buffers
このパラメーターは、各データベースセッションで使用される一時バッファーの最大数を設定します。セッションローカルバッファは、一時テーブルへのアクセスにのみ使用されます。このパラメータの設定は、個々のセッション内で変更できますが、セッション内で一時テーブルを最初に使用する前にのみ変更できます。
PostgreSQLデータベースは、このメモリ領域を使用して各セッションの一時テーブルを保持します。これらは、接続が閉じられるとクリアされます。
temp_bufferのデフォルト値=8MB。
結論
パフォーマンスを向上させるには、メモリアーキテクチャを理解し、適切なパラメータを調整することが重要です。これは、ワークロードの高いシステムで特に必要です。より一般的なパフォーマンス調整のヒントについては、PostgreSQLのこのパフォーマンスチートシートを確認してください。