PostgreSQL:データをメモリに強制します


32

PostgreSQLに特定のテーブルをメモリにロードさせる、または少なくともディスクから読み取ってシステムにキャッシュされるようにするための体系的な方法はありますか?

回答:


25

メーリングリストのトピックの 1つに興味があるかもしれません。TomLane (コア開発者)が答えています

[..]しかし、私の意見では、LRUキャッシングアルゴリズムよりも賢いと思っている人は一般的に間違っています。テーブルが非常に頻繁に使用される場合、メモリ内に問題なく残ります。LRUアルゴリズムに従ってメモリ内にとどまるほど十分に使用されていない場合は、メモリスペースを実際に他の何かに費やす必要があります。[..]

また、SOの質問に興味があるかもしれません:https : //stackoverflow.com/questions/486154/postgresql-temporary-tablesおよび多分より快適なhttps://stackoverflow.com/questions/407006/need-to-load-the -whole-postgresql-database-into-the-ram


1
+1他のRDBMSにも同じ考え方が当てはまります。
gbn

25
はいといいえ。一部のOracleテーブルはメモリ内でロックされます。これは、頻繁に使用されない可能性があることがわかっているためですが、使用される状況では、待ち時間が致命的です。DBは常にDBAに最終決定権を与える必要があります(別の例は、クエリオプティマイザーへのヒントです)。
ガイウス

35

Postgres 9.4は、最終的にリレーションからOSまたはデータベースバッファーキャッシュにデータをプリロードするための拡張機能を追加しました(任意)。

pg_prewarm

これにより、フル稼働パフォーマンスをより迅速に達成できます。

データベースで1回実行します(詳細な手順はこちら):

CREATE EXTENSION pg_prewarm;

その後、特定のリレーションをプリロードするのは簡単です。基本的な例:

SELECT pg_prewarm('my_tbl');

my_tbl検索パスで指定された最初のテーブルを見つけて、それをPostgresバッファキャッシュにロードします

または:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetchサポートされている場合、オペレーティングシステムに非同期プリフェッチ要求を発行します。サポートされていない場合は、エラーをスローします。read 要求されたブロックの範囲を読み取ります。とは異なりprefetch、これは同期であり、すべてのプラットフォームとビルドでサポートされていますが、より遅い場合があります。buffer要求されたブロックの範囲をデータベースバッファキャッシュに読み込みます。

デフォルトはでbuffer、これは最大の影響(コストが高く、効果が大きい)を持っています。

詳細についてはマニュアルを参照してください、引用はそこからです。
Depeszもそれについてブログに書いています。


4

一般的な場合、十分なRAMがあれば、通常はデータベースサービスを信頼して、RAMで定期的に使用するものを適切に保持することができます。一部のシステムでは、テーブルを常にRAMに保持するようにヒントを出すことができます(頻繁に使用されない小さなテーブルに便利ですが、使用するときはできるだけ早く応答することが重要です)が、pgsqlにそのようなテーブルヒントがある場合他のものをキャッシュするために使用できるメモリ量を減らしているため、アプリケーション全体の速度が低下する可能性があるため、これらの使用には非常に注意する必要があります。

起動時にデータベースのページキャッシュを準備する場合(たとえば、再起動や、DBがキャッシュされているものをすべて忘れるようなメンテナンス操作の後)、次のスクリプトを作成します。

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(最後のステップが各インデックスまたはコースに対して繰り返され、ORDER BY句のフィールドが正しい順序になるように注意してください)

上記を実行すると、すべてのデータとインデックスページが読み込まれ、RAMページキャッシュに(少なくともしばらくは)読み込まれるはずです。アプリケーションデータベース用のこのようなスクリプトは、再起動後に実行されるため、その後システムにログインする最初のユーザーの応答が遅くなることはありません。データベース定義テーブル(MSSQLのsys.objects/ sys.indexes/ など)をスキャンする代わりに、このようなスクリプトを手書きする方が良いsys.columnsでしょう。その後、時間がかかるすべてをスキャンするのではなく、最も一般的に使用されるインデックスを選択的にスキャンできます。


3
これは、少なくともPostgreSQLでは機能しません。バッファキャッシュ全体が使用されるのを防ぐために、小さい(256KB)リングバッファが順次スキャン用の共有バッファから割り当てられます。詳細については、github.com / postgres / postgres / blob / master / src / backend / storage /…を参照してください。これを確認するには、大きなテーブルからSELECT *を実行し、pg_buffercacheテーブル(pg_buffercache拡張から)を調べます。
hbn

そこにこんにちは@hbnが、スレッドの保存この中にこいつ男はそれが動作することを言う- dba.stackexchange.com/a/36165/55752
scythargon

@scythargonはOSキャッシュに格納される可能性がありますが、PostgreSQLバッファキャッシュには格納されません。あなたが私を信じないなら、私が上で提案したことを試してください。
hbn

Postgres 9.5では、SELECT * FROM schema.table60GiBテーブル全体を100GiB PostgreSQLバッファキャッシュにロードしようとしました。
須藤

1

同様の問題がありました:
サーバーサービスを再起動し、キャッシュされたデータがすべて削除された後、必要なすべてのインデックスとデータがキャッシュされるまで、多くのクエリが最初に呼び出され、本当に遅くなり、クエリの特定の複雑さが発生しました。つまり、たとえば、ユーザーは「アイテム」ごとに1回(実行時間1〜3秒)および関連データを5,000万行からヒットする必要があるため、ユーザーは不要な遅延を経験しなくなります。ユーザーが迷惑なハングを経験するまでに最初の3時間かかります。ほとんどの使用済みデータがキャッシュされ、プログラムが実稼働パフォーマンスで一流を台無しにし、それでも2日目は、わずかにアクセスされたデータが少なくなると突然の短い遅延が続きます... 、統計データなど。

これを解決するために、大きなインデックスを持つ最も使用量の多いテーブルで選択を実行する小さなpythonスクリプトを作成しました。実行に15分かかり、パフォーマンスの遅延はありませんでした。


0

うーん、COPYコマンドが役立つかもしれません。COPYを実行してstdoutから読み取ります。pg_dumpを使用して実行できます。

pg_dump -U <user> -t <table> <database> > /dev/null

他の方法は、すべてのテーブルファイルを見つけて実行することcat <files> > /dev/nullです。

テーブルのファイル名を取得する方法の例を次に示します。

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

そのため、テーブルのファイルは/ path / to / pgsql / data / base / 16384/24576 *です

インデックスとトーストテーブルも同様に読み取り、それらのOIDを同じ方法で取得したいと考えています。

ところで、なぜあなたはそれが必要なのですか?postgresqlとOSは、最もホットなデータをキャッシュし、良好な状態を維持するのに十分スマートだと思います。キャッシュ効率。


0

QSoftのRamDriveを使用します。これは、Windows用の最速のRAMディスクとしてベンチマークされました。使ったばかり

initdb -D e:\data

ここで、e:\はRamDiskの場所です。


5
WindowsのPGは、* nix(RAMに依存しない)よりもWindowsの方がはるかに遅いため、実稼働サイトにはかなり勇敢な選択です。
DrColossos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.