PostgreSQLは垂直方向にかなりうまくスケーリングできます。 PostgreSQLサーバーで利用できるリソース(CPU、メモリ、ディスク)が多いほど、パフォーマンスが向上します。ただし、Postgresの一部は増加したリソースを自動的に利用できますが、他の部分は改善に気付く前に構成を変更する必要があります。
PostgreSQLが実行しているシステムを最大限に活用する方法の詳細については、以下をお読みください。
CPU
PostgreSQLには、マスタープロセス( postmaster と呼ばれる)で構成される従来のプロセスアーキテクチャがあります。 )新しいプロセス(バックエンドと呼ばれる)を生成します )新しいクライアント接続ごとに。これは、使用可能なCPUコアが多い場合、より多くのプロセスを同時に実行できることを意味します。したがって、バックエンドはCPUの可用性についてそれほど競合する必要はありません。 CPUバウンドクエリはより速く完了します。
システム全体、データベースごと、またはユーザーごとのレベルで、最大許容同時接続を調整することをお勧めします。
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
不正なアプリが多くの接続を占有してしまうことがないようにします。
PostgreSQLサーバーは、バキューム、レプリケーション、サブスクリプション(論理レプリケーションの場合)などのハウスキーピングタスクを処理するプロセスを生成できます。このようなワーカーの数は動的に決定されるのではなく、構成によって設定されるだけで、デフォルトは8です。
ワーカープロセス数の最上位の構成設定は次のとおりです。
# typically specified in postgresql.conf
max_worker_processes = 16
この値を増やすとできます その結果、メンテナンスジョブ、並列クエリ、インデックス作成が高速化されます。
バージョン9.6以降、Postgresは、queryplannerが役立つと判断した場合、クエリを並行して実行できます。並列クエリでは、ワーカーを生成し、ワーカー間で作業を分散してから、結果を収集(収集)します。max_worker_processes
の全体的な制限に従います。 以前に設定したPostgresは、2つの構成設定の値に応じて、並列クエリ用に生成できるワーカーの数を決定します。
# the maximum number of workers that the system can
# support for parallel operations
max_parallel_workers = 8
# the maximum number of workers that can be started
# by a single Gather or Gather Merge node
max_parallel_workers_per_gather = 8
アイドル状態のCPUと並列化可能なクエリがある場合、これらの値を増やすと、そのようなクエリを高速化できます。
Postgres 11では、Bツリーインデックスの並列作成のサポートが追加されました。 Bツリーインデックスを定期的に作成するか、インデックスを再作成する場合は、この値を増やすと次のようになります。
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
これにより、Postgresはこれらの多くのワーカーを生成できます(max_worker_processes
の全体的な制限に従います) )Bツリーインデックスの作成を高速化します。
論理レプリケーション(Postgres 10以降で利用可能)は、サブスクリプション側のワーカープロセスに依存して、パブリッシャーから変更をフェッチします。 Postgresに、より多くの論理レプリケーションワーカーを生成するように依頼することで、特にテーブルが多い場合に、変更をフェッチして並行して適用できます。この構成設定により、レプリケーションワーカーの総数が増加します。
# maximum number of logical replication workers
max_logical_replication_workers = 8
ストリーミングレプリケーションでは、ベースバックアップとの同期を開始できます。ただし、論理的な複製では、ネットワークを介して複製プロトコル自体を介して変更を取り込む必要があります。これには時間がかかる場合があります。同期フェーズでより多くの作業者を許可すると、このプロセスをスピードアップできます:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
定期的に、一連の構成設定に基づいて、PostgresはデータベーステーブルをVACUUMする多数のワーカーを生成します。もちろん、これはautovacuumと呼ばれ、autovacuumランチャーが毎回生成するワーカーの数は構成設定を介して設定できます。
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
WAL圧縮
CPUに余裕がある場合は、WALファイルに書き込まれるページを圧縮することで、CPUをディスク帯域幅と交換できます。これにより、ディスクに書き込む必要のあるデータの量が減りますが、データを圧縮するためのCPUサイクルが増えます。また、ストリーミングレプリケーションのためにネットワーク経由で送信する必要のあるデータのサイズを削減します。
実際には、WAL圧縮の利点は、非常に合理的なオーバーヘッドの価値が十分にあります。オンにするには、次を使用します:
# compresses full page images written to WAL
wal_compression = on
OSは、最近ディスクとの間で読み書きされたデータをキャッシュするために、アプリケーションで使用されていないメモリを自動的に管理および使用します。これにより、ディスクを大量に消費するアプリケーション、そして確かにPostgreSQLが大幅に高速化されます。
Postgresで最も人気のあるホストであるLinuxでは、OSディスクキャッシュのサイズをユーザーが設定することはできません。管理はLinuxの内部です。メモリの負荷がかかると、アプリケーションにディスクキャッシュメモリが割り当てられます。
クエリプランナーは、OSによって提供されるディスクキャッシュの量を要素として見積もりに含める必要があります。 (使用可能なメモリを増やすことで)OSディスクキャッシュを大幅に増やすことができた場合は、この構成設定を増やすと、プランナーの見積もりを改善できる可能性があります。
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
PostgreSQLは、すべてのワーカーとバックエンドプロセス間で共有される一連のバッファーを使用します。これらは共有バッファと呼ばれます 、および共有バッファに割り当てられるメモリの量は、構成設定を使用して設定されます。
shared_buffers = 32GB
クエリによって一時テーブルにアクセスすると、読み込まれたコンテンツをキャッシュするためにバッファが割り当てられます。このバッファのサイズは、構成設定を使用して設定されます。
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
予備のメモリがあり、一時テーブルを頻繁に使用するクエリがある場合は、この値を増やすと、そのようなクエリを高速化できます。
ワーキングメモリは、バックエンドによってローカルおよびプライベートに割り当てられます。これは、一時テーブルを作成せずに並べ替えと結合を実行するために使用されます。これをデフォルトの4MBから増やすと、一時テーブルの作成中にクエリをより速く完了することができます。
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
VACUUM、インデックス作成、およびその他のそのようなメンテナンスコマンドで使用されるメモリは、構成設定maintenance_work_mem
によって制御されます。 。この量を増やすと、特に再作成が必要なインデックスまたはテーブルで、これらの操作を高速化できます。
自動バキュームワーカーが使用するメモリは、メンテナンスワークメモリから取得できます(autovacuum_work_mem = -1
を設定することにより) )または個別に構成します。
# the maximum amount of memory to be used by
# maintenance operations
maintenance_work_mem = 128MB
# maximum amount of memory to be used by each
# autovacuum worker process
autovacuum_work_mem = -1
ディスクは、より大きく、より速く、またはより同時に作成できます。ディスクのサイズは、PostgreSQLに指示する必要がない唯一のものです。デフォルトでは、PostgreSQLは使用可能なディスクスペースの使用を制限しません。これは通常は問題ありません。
ただし、作成される一時ファイルの合計サイズに制限を設定して、10億行などを並べ替えようとするクエリに対してある程度の保護を提供することができます。
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
RAID化されたディスクやZFSのようなファイルシステムは、より多くの同時実行性をサポートするようにセットアップできます。つまり、データを内部で保存または処理する方法により、このようなファイルシステムによっていくつかのディスク読み取り/書き込みが同時に処理される可能性があります。
次の構成設定を使用して、Postgresに複数の同時ディスクI/Oを発行させることができます。
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
これは現在、ビットマップヒープスキャンでのみ使用されています。
Postgresクエリプランナーは、シーケンシャル読み取りがランダム読み取りよりも高速であると想定しています。正確にどれだけ速く調整できる値です。デフォルトでは、ランダム読み取りのコストは4倍であると想定しています。
ディスクの設定、ワークロード、ベンチマークに応じて、ランダム読み取りがシーケンシャル読み取りの2倍のコストであることが確実な場合は、Postgresにそのことを伝えることができます。
# the planner's estimate of the cost of a disk page
# fetch that is part of a series of sequential fetches
seq_page_cost = 1
# the planner's estimate of the cost of a
# non-sequentially-fetched disk page
random_page_cost = 2
1つの大きな単一ファイルシステムとしてマウントされていない複数のディスクを利用するには、テーブルスペースを使用できます。テーブルスペースを使用すると、テーブルを配置したり、異なるファイルシステムにインデックスを付けたりできます。これにより、同時実行性が向上し、テーブルの増加を処理する簡単な方法が提供されます。
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
表領域について詳しくは、こちらをご覧ください。
ネットワークは通常、PostgreSQLサーバーで最も使用されていないリソースであり、飽和状態になることはめったにありません。拡張する必要がある場合は、それぞれが独自のIPを持つネットワークインターフェイスをさらに追加して、PostreSQLにそれらすべてをリッスンさせるのは簡単です。
listen_addresses = '10.1.0.10,10.1.0.11'
クライアントは、PostgreslistensがオンになっているすべてのIP間で負荷分散する必要があります。
微調整できる構成設定は他にもいくつかありますが、そのほとんどはより多くのCPUを消費します メモリ。
Postgres 10ではテーブルパーティショニングが導入されました。これはPostgres11で改善されました。パーティションの一部のクエリ最適化は、CPUとメモリの消費量が増える可能性があるため、デフォルトではオンになっていません。これらは次のとおりです。
# allow a join between partitioned tables to be
# performed by joining the matching partitions
enable_partitionwise_join = on
# allow grouping or aggregation on a partitioned
# tables performed separately for each partition
enable_partitionwise_aggregate = on