「マテリアライズドビュー」として機能する独自のテーブルをいつでも実装できます。それはあなたが前にしなければならなかったことですMATERIALIZED VIEW
は、Postgres 9.3でいずれに実装されるに。
たとえば、プレーンを作成できますVIEW
。
CREATE VIEW graph_avg_view AS
SELECT xaxis, AVG(value) AS avg_val
FROM graph
GROUP BY xaxis;
そして、結果全体を一度、または最初からやり直す必要があるたびに具体化します。
CREATE TABLE graph_avg AS
SELECT * FROM graph_avg_view
(またはSELECT
、VIEW
。を作成せずにステートメントを直接使用します。)
次に、ユースケースの非公開の詳細に応じて、DELETE
/ UPDATE
/INSERT
手動で変更します。
テーブルのデータ変更CTEをそのまま使用した基本的なDMLステートメント:
誰も同時に書き込みをしようとしないと仮定しgraph_avg
ます(読み取りは問題ありません):
WITH del AS (
DELETE FROM graph_avg t
WHERE NOT EXISTS (SELECT 1 FROM graph_avg_view v WHERE v.xaxis = v.xaxis);
)
, upd AS (
UPDATE graph_avg t
FROM graph_avg_view v
WHERE t.xaxis = v.xaxis
AND t.avg_val <> v.avg_val
)
INSERT INTO graph_avg t
SELECT *
FROM graph_avg_view v
LEFT JOIN graph_avg t USING (xaxis)
WHERE t.xaxis IS NULL;
しかし、これはおそらく最適化されるべきです。
基本的なレシピ:
- 基本表に
timestamp
デフォルトの列を追加しnow()
ます。それを呼び出しましょうts
。
- 更新がある場合は、トリガーを追加して、
xaxis
またはを変更するすべての更新で現在のタイムスタンプを設定しますvalue
。
最新のスナップショットのタイムスタンプを記憶する小さなテーブルを作成します。それを呼び出しましょうmv
:
CREATE TABLE mv (
tbl text PRIMARY KEY
, ts timestamp NOT NULL DEFAULT '-infinity'
); -- possibly more details
この部分的な複数列インデックスを作成します。
CREATE INDEX graph_mv_latest ON graph (xaxis, value)
WHERE ts >= '-infinity';
クエリの述語として最後のスナップショットのタイムスタンプを使用して、完全なインデックス使用でスナップショットを更新します。
トランザクションの最後に、インデックスを削除し、インデックス述語のタイムスタンプを(最初に'-infinity'
)トランザクションタイムスタンプで置き換えて再作成 します。これはテーブルにも保存します。1つのトランザクションですべて。
なお、部分インデックスがカバーに偉大であることINSERT
及びUPDATE
操作ではなくDELETE
。それをカバーするには、テーブル全体を考慮する必要があります。すべて厳密な要件に依存します。