テーブルの最終変更時刻の信頼できる信頼できる記録はありません。relfilenodeの使用は、多くの理由で間違っています。
書き込みは最初に書き込みヘッドログ(WAL)に記録され、次にヒープ(テーブルファイル)に遅延記録されます。レコードがWALに入ると、Pgはそれを急いでヒープに書き込むことはなく、次のシステムチェックポイントまで書き込まれないこともあります。
大きなテーブルには複数のフォークがあるため、すべてのフォークをチェックして最新のタイムスタンプを選択する必要があります。
シンプルSELECT
は、ヒントビットの設定により、基になるテーブルへの書き込みアクティビティを生成できます。
autovaccumおよびユーザーの表示データを変更しないその他のメンテナンスは、関係ファイルを変更します。
のような一部の操作はvaccum full
、relfilenodeを置き換えます。適切なロックを取得せずに同時に表示しようとしている場合、期待した場所にならない可能性があります。
いくつかのオプション
信頼性が必要ない場合は、pg_stat_database
およびの情報を潜在的に使用できますpg_stat_all_tables
。これらは、最後の統計リセットの時間と、最後の統計リセット以降のアクティビティ統計を提供できます。最新のアクティビティがいつであったかはわかりませんが、最後の統計がリセットされてからのことであり、統計がリセットされる前に何が起こったかについての情報はありません。制限されていますが、すでにあります。
確実に行うための1つのオプションは、トリガーを使用して、各テーブルの最終変更時刻を含むテーブルを更新することです。これを行うと、テーブルへのすべての書き込みがシリアル化され、同時実行性が失われることに注意してください。また、すべてのトランザクションにかなりのオーバーヘッドが追加されます。お勧めしません。
わずかに少ないひどい代替が使用することですLISTEN
とNOTIFY
。外部のデーモンプロセスをPostgreSQLに接続しLISTEN
、イベントに接続させます。ON INSERT OR UPDATE OR DELETE
トリガーを使用NOTIFY
して、テーブルoidを通知ペイロードとして、テーブルが変更されたときにs を送信します。これらは、トランザクションのコミット時に送信されます。デーモンは変更通知を蓄積し、それらをデータベースのテーブルに遅延的に書き戻すことができます。システムがクラッシュした場合、最新の変更の記録は失われますが、大丈夫です。クラッシュ後に起動する場合は、すべてのテーブルを変更されたものとして扱います。
最悪の同時実行性の問題を回避するために、代わりに、before insert or update or delete or truncate on tablename for each statement execute
トリガーとしてリレーションoidをパラメーターとして使用するように一般化された変更タイムスタンプを記録できます。これ(relation_oid, timestamp)
により、変更ログテーブルにペアが挿入されます。次に、別の接続でヘルパープロセスを使用するか、アプリから定期的に呼び出され、そのテーブルを最新の情報に集約し、最新の変更のサマリーテーブルにマージして、ログテーブルを切り捨てます。listen / notifyアプローチに対するこの唯一の利点は、クラッシュ時に情報を失わないことです-しかし、それはさらに効率的でもありません。
別のアプローチは、テーブルの変更をトラップし、統計情報を遅延更新するためProcessUtility_hook
にExecutorRun_hook
(など)、などを使用するC拡張関数を記述することです。私はこれがどれほど実用的であるかを見ていない。ソースのさまざまな_hookオプションを見てください。
最善の方法は、統計情報コードをパッチしてこの情報を記録し、コアに含めるためにPostgreSQLにパッチを送信することです。コードを書くことから始めないでください。十分に定義された方法が十分にあると考えたら、-hackersでアイデアを上げます(つまり、コードを読むことから始め、「どうやって...」と尋ねるだけではありません)。に最終更新時間を追加するのは良いかもしれませんがpg_stat_...
、コミュニティにオーバーヘッドの価値があると納得させるか、オプションで追跡する方法を提供する必要があります -そして、統計を保持するためのコードを記述し、パッチを提出してください。この機能を必要とする人だけがそれを気にするからです。
どうやってやる
これを行う必要があり、それを適切に行うためのパッチを作成する時間がなかった場合、おそらく上で概説したlisten / notifyアプローチを使用するでしょう。
PostgreSQL 9.5コミットタイムスタンプの更新
更新:PostgreSQL 9.5にはコミットタイムスタンプがあります。あなたは彼らがで有効になっている場合はpostgresql.conf
(あまりにも過去にそうしました)、あなたは最大で行のコミットのタイムスタンプを確認することができますxmin
して近似する最終更新時間を。最新の行が削除された場合、それらはカウントされないため、これは近似値にすぎません。
また、コミットタイムスタンプレコードは限られた時間だけ保持されます。そのため、あまり変更されていないテーブルがいつ変更されたかを知りたい場合、答えは事実上「しばらく前」になります。