大きなテーブルを扱っていると仮定します 、部分インデックス 役立つかもしれません:
CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC)
WHERE created_at > '2013-09-15 0:0'::timestamp;
すでにお気づきのとおり、ここでは降順または昇順はほとんど問題になりません。 Postgresはほぼ同じ速度で逆方向にスキャンできます(例外は複数列のインデックスに適用されます)。
このインデックスを使用するためのクエリ:
SELECT * FROM tbl
WHERE created_at > '2013-09-15 0:0'::timestamp -- matches index
ORDER BY created_at DESC
LIMIT 1;
ここでのポイントは、インデックスをはるかに小さくすることです。 、したがって、キャッシュと保守が簡単になるはずです。
- 最新のタイムスタンプよりも小さいことが保証されているタイムスタンプを選択する必要があります。
- 古いデータを切り取るために、時々インデックスを再作成する必要があります。
- 条件は
IMMUTABLE
である必要があります 。
したがって、1回限りの効果は時間の経過とともに低下します。 特定の問題 ハードコードされた条件です:
WHERE created_at > '2013-09-15 0:0'::timestamp
自動化
インデックスとクエリは時々手動で更新できます。または、次のような関数を使用して自動化します。
CREATE OR REPLACE FUNCTION f_min_ts()
RETURNS timestamp LANGUAGE sql IMMUTABLE AS
$$SELECT '2013-09-15 0:0'::timestamp$$
インデックス:
CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC);
WHERE created_at > f_min_ts();
クエリ:
SELECT * FROM tbl
WHERE created_at > f_min_ts()
ORDER BY created_at DESC
LIMIT 1;
cronジョブまたはトリガーベースのイベントを使用してレクリエーションを自動化します。クエリは同じままになります。ただし、すべてのインデックスを再作成する必要があります この関数を変更した後、何らかの方法でこの関数を使用します。それぞれをドロップして作成するだけです。
最初..
...これで実際にボトルの首に当たっているかどうかをテストします。
単純なDROP index ... ; CREATE index ...
仕事をします。次に、インデックスが肥大化した可能性があります。自動真空設定がオフになっている可能性があります。
または、VACUUM FULL ANALYZE
をお試しください テーブル全体とインデックスを元の状態に保ち、もう一度確認します。
その他のオプション テーブルから実際に取得するものに応じて、通常の一般的なパフォーマンスチューニングとカバーインデックスを含めます。