メモリ容量を大きくするとPostgreSQLの処理が速くなるのはなぜか?

PostgreSQLを運用しているシステムのメモリ容量を大きくして、設定を見直すと処理が速くなる場合がありますが、それはなぜでしょうか?
この記事では、その理由についてまとめています。

以前、LinuxとRDBMSについて書きましたが、今回はPostgreSQLについて書きます。

TL;DR

この記事では、PostgreSQLを運用しているシステムのメモリ容量を大きくして、設定を見直すと処理が速くなる理由として、以下について書いています。

  • 共有バッファ(shared_buffers)の容量を大きくすると、キャッシュできるテーブルやインデックスのサイズが大きくなるので、処理が速くなる

  • 作業メモリ(work_mem)の容量を大きくすると、クエリ実行時に行われる、並び替えやハッシュテーブル操作のために使えるメモリのサイズが大きくなるので、処理が速くなる

参考

この記事では、[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則を参考にしています。

PostgreSQLとはなにか?

PostgreSQLは、OSSのRDBMSでマルチプロセスタイプのアーキテクチャです。

プロセス

RDBMSは、クエリの処理をはじめとして、バッファの管理、ストレージへの書き込み制御、統計情報の収集など、様々な制御を行っています。
PostgreSQLは、複数のプロセスを動作させることで、複雑な制御を可能としています。

マスタープロセス

PostgreSQLを起動すると、マスタープロセスが起動します。
マスタープロセスは、PostgreSQLを制御する様々なプロセス(バックグラウンドプロセス)や、外部からの接続を受け付け、接続に対応するプロセス(バックエンドプロセス)を起動します。

バックエンドプロセス

バックエンドプロセスは、クライアントから接続要求を受けたときに生成されるプロセスです。
クエリの実行はバックエンドプロセスで実行されます。
クエリ、結果の送受信などは、クライアントとバックエンドプロセスの間で行われます。

メモリ管理

PostgreSQLで使われるメモリは、サーバプロセス全体で共有される共有メモリ域とバックエンドプロセスで確保されるプロセスメモリ域の2つに区分されます。

共有メモリ域

共有メモリ域は、バックグラウンドプロセスとバックエンドプロセスのすべてから参照、更新されるメモリ領域です。

共有バッファ(shared_buffers)

共有メモリ域の中に共有バッファ(shared_buffers)という領域があります。
共有バッファ(shared_buffers)はテーブルやインデックスのデータをキャッシュする領域です。

プロセスメモリ域

プロセスメモリ域はバックエンドプロセスごとに確保されるメモリ領域です。
メモリ領域を確保したプロセスのみが参照可能です。

作業メモリ(work_mem)

プロセスメモリ域の中に作業メモリ(work_mem)という領域があります。
作業メモリ(work_mem)はクエリ実行時に行われる、並び替えとハッシュテーブル操作のために使われる領域です。

メモリの設定

PostgreSQLは、データなどをデータベースファイルとしてHDDに保存することで、データの永続化を実現しています。
一般的には、HDDからデータを取り出す場合とメモリからデータを取り出す場合では、数百倍から数十万倍の性能差があると言われています。
PostgreSQLは、メモリの性能を活かすためにデータアクセス時にデータベースのファイルをページ単位でメモリ上に展開し、データに繰り返しアクセスする場合の処理性能を高めています。
一般的に、データベースに保存されるデータの量はサーバのメモリ容量よりも大きいため、すべてのデータをメモリ上で処理することはできません。
データベースの性能を高めるために、メモリの活用は重要で、メモリの設定は適切にする必要があります。
では、メモリの設定にはどのようなものがあるのでしょうか?

共有バッファ(shared_buffers)の設定

まず、共有バッファ(shared_buffers)の設定があります。
共有バッファ(shared_buffers)の容量を大きくすると、キャッシュできるテーブルやインデックスのデータのサイズが大きくなります。
キャッシュできるテーブルやインデックスのデータのサイズが大きくなると、テーブルやインデックスへのアクセスが速くなる場合があります。
ただし、バッファ探索にかかる時間が大きくなるので注意が必要です。

作業メモリ(work_mem)の設定

つぎに、作業メモリ(work_mem)の設定があります。
作業メモリ(work_mem)の容量を大きくすると、クエリ実行時に行われる、並び替えやハッシュテーブル操作のために使えるメモリのサイズが大きくなります。
クエリ実行時に使えるメモリのサイズが大きくなると、多くのメモリを必要とする処理を選択できるようになり、処理が速くなる場合があります。
ただし、複雑な問い合わせの場合、並び替えやハッシュテーブル操作が問い合わせの中で複数回実行されることがあります。
その場合、メモリが不足してスワップが発生してしまう可能性があるので注意が必要です。

まとめ

この記事では、PostgreSQLを運用しているシステムのメモリ容量を大きくして、設定を見直すと処理が速くなる理由として、以下について書きました。

  • 共有バッファ(shared_buffers)の容量を大きくすると、キャッシュできるテーブルやインデックスのサイズが大きくなるので、処理が速くなる

  • 作業メモリ(work_mem)の容量を大きくすると、クエリ実行時に行われる、並び替えやハッシュテーブル操作のために使えるメモリのサイズが大きくなるので、処理が速くなる

この記事が気に入ったらサポートをしてみませんか?