Postgresql 9.1 に数百万行の大きなテーブルがあります。列の 1 つはタイム ゾーン付きのタイムスタンプです。
頻繁に使用されるクエリは、where 句'column > (now()::date - 11)'
を使用して過去 10 日間のデータを検索します。
スキャンを制限するために、先月のデータに対してのみ機能するインデックスを作成したいと考えています。部分索引。
これまでのところ、先月の実際の使用方法がわからなかったので、インデックスの開始日として「2015-12-01」をハードコーディングすることから始めました。
create index q on test (i) where i > '2015-01-01';
これはうまくいき、インデックスが作成されました。残念ながら、::timestamp
クエリは::date
. そのため、インデックスは使用されず、振り出しに戻りました。
次に、列を日付と比較するようにインデックスを変更して、一致するようにしました。しかし、ここで不変の壁にぶち当たります。
to_date
またはcast as date
変更可能な関数であるため、それらはローカルのタイムゾーンに依存しているため、インデックスの作成は失敗します。
次のようなテストテーブルがある場合:
create table test (i timestamptz);
次に、インデックスを作成しようとします
create index q on test (i) where i > to_date('2015-01-01','YYYY-DD-MM');
その後、失敗します
ERROR: functions in index predicate must be marked IMMUTABLE
これは理解できます。しかし今、特定のタイムゾーンで試してみると
create index q on test (i) where i > to_date('2015-01-01','YYYY-DD-MM')
at time zone 'UTC';
それでも失敗する
ERROR: functions in index predicate must be marked IMMUTABLE
これはもうわかりません。タイムゾーンが定義されています。他に何が不変ですか?
私も自分で不変関数を作成しようとしました:
CREATE FUNCTION
datacube=# create or replace function immutable_date(timestamptz) returns date as $$
select ($1::date at time zone 'UTC')::date;
$$ language sql immutable;
しかし、インデックスでこの関数を使用します:
create index q on test (i) where i > immutable_date('2015-01-01');
同じエラーで失敗します:
ERROR: functions in index predicate must be marked IMMUTABLE
私はここで途方に暮れています。タイムゾーンだけでなく、ロケールと関係があるのでしょうか?または、他の何かがそれを変更可能にしますか?
また、インデックスを先月または 2 か月のデータに制限する別のより簡単な方法があるでしょうか? Postgres でテーブルを分割するには、データベース全体を再構築する必要がありますが、これまでのところ他に何も見つかりませんでした。