now()
を使用すると例外が発生します 関数がIMMUTABLE
ではないため (明らかに)そして、マニュアルを引用します
:
(はるかに効率的な)部分インデックスを利用する2つの方法があります:
1。 定数を使用した条件付きの部分インデックス 日付:
CREATE INDEX queries_recent_idx ON queries_query (user_sid, created)
WHERE created > '2013-01-07 00:00'::timestamp;
想定 created
実際にはtimestamp
として定義されています 。 timestamp
を提供することはできません timestamptz
の定数 列(timestamp with time zone
)。 timestamp
からのキャスト timestamptz
へ (またはその逆)現在のタイムゾーン設定に依存し、不変ではありません 。一致するデータ型の定数を使用します。タイムゾーンがある場合とない場合のタイムスタンプの基本を理解する:
ドロップして再作成 トラフィックが少ない時間帯のインデックス、おそらく毎日または毎週のcronジョブ(またはあなたにとって十分なもの)。インデックスの作成は非常に高速で、特に部分インデックスは比較的小さいです。このソリューションでも、テーブルに何も追加する必要はありません。
同時アクセスなしを想定 テーブルに対して、自動インデックス再作成は次のような関数で実行できます:
CREATE OR REPLACE FUNCTION f_index_recreate()
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
DROP INDEX IF EXISTS queries_recent_idx;
EXECUTE format('
CREATE INDEX queries_recent_idx
ON queries_query (user_sid, created)
WHERE created > %L::timestamp'
, LOCALTIMESTAMP - interval '30 days'); -- timestamp constant
-- , now() - interval '30 days'); -- alternative for timestamptz
END
$func$;
電話:
SELECT f_index_recreate();
now()
(あなたが持っていたように)はCURRENT_TIMESTAMP
と同等です timestamptz
を返します 。 timestamp
にキャストします now()::timestamp
を使用 またはLOCALTIMESTAMP
を使用します 代わりに。
db <> fiddle こちら
古い
同時アクセスに対処する必要がある場合 テーブルに、DROP INDEX CONCURRENTLY
を使用します およびCREATE INDEX CONCURRENTLY
。ただし、これらのコマンドを関数にラップすることはできません。ドキュメントごと
:
したがって、2つの別々のトランザクション :
CREATE INDEX CONCURRENTLY queries_recent_idx2 ON queries_query (user_sid, created)
WHERE created > '2013-01-07 00:00'::timestamp; -- your new condition
次に:
DROP INDEX CONCURRENTLY IF EXISTS queries_recent_idx;
必要に応じて、古い名前に名前を変更します:
ALTER INDEX queries_recent_idx2 RENAME TO queries_recent_idx;
2。 「アーカイブされた」タグを条件とする部分インデックス
archived
を追加します テーブルにタグを付ける:
ALTER queries_query ADD COLUMN archived boolean NOT NULL DEFAULT FALSE;
UPDATE
古い行を「廃止」し、次のようなインデックスを作成するために、選択した間隔で列を作成します。
CREATE INDEX some_index_name ON queries_query (user_sid, created)
WHERE NOT archived;
クエリに一致条件を追加して(冗長に見える場合でも)、インデックスを使用できるようにします。 EXPLAIN ANALYZE
で確認してください クエリプランナーがキャッチするかどうか-新しい日付のクエリにインデックスを使用できる必要があります。ただし、正確に一致しない、より複雑な条件は理解できません。
インデックスを削除して再作成する必要はありませんが、UPDATE
テーブル上では、インデックスの再作成よりも費用がかかる可能性があり、テーブルは少し大きくなります。
最初で行きます オプション(インデックスの再作成)。実際、私はこのソリューションをいくつかのデータベースで使用しています。 2つ目は、よりコストのかかる更新が発生します。
どちらのソリューションも時間の経過とともにその有用性を維持し、より古い行がインデックスに含まれるため、パフォーマンスは徐々に低下します。