クエリの統合
いくつかの場所でロジックを改善することで、操作全体を1つのクエリに統合できます。 SQL関数へのラップはオプションです:
CREATE OR REPLACE FUNCTION f_elems(_action_id integer)
RETURNS SETOF integer AS
$func$
WITH RECURSIVE l AS (
SELECT a.category_id, l.local_id
FROM action a
JOIN local l USING (local_id)
WHERE a.action_id = $1
UNION ALL
SELECT l.category_id, c.local_id
FROM l
JOIN local c ON c.parent_id = l.local_id -- c for "child"
)
SELECT e.element_id
FROM l
JOIN element e USING (category_id, local_id);
$func$ LANGUAGE sql STABLE;
すべてのelement_id
を取得します 特定のaction_id
の同じローカルおよび子ローカルの場合 。
電話:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
db <> fiddle こちら
OLD sqlfiddle
これは実質的に必要です いくつかの理由ですでに速くなっています。最も明白なものは次のとおりです:
- plpgsqlの低速ループを純粋なSQLに置き換えます。
- 再帰クエリの開始セットを絞り込みます。
- 不要で悪名高い
IN
を削除します 構築します。
SELECT * FROM ...
で呼び出しています SELECT
だけでなく 、行に列が1つしかない場合でも、OUT
の列名を取得します パラメータ(element_id
)関数ヘッダーで宣言しました。
もっと速く、まだ
インデックス
action.action_id
のインデックス 主キーによって提供されます。
ただし、local.parent_id
のインデックスを見逃している可能性があります 。その間、複数列のインデックスをカバーするようにします。 (Postgres 9.2 +)with parent_id
最初の要素およびlocal_id
として 2番目として。テーブルがlocal
の場合、これは大いに役立つはずです。 大きい。小さなテーブルではそれほど多くないか、まったくない:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
なんで?参照:
最後に、複数列のインデックス
テーブルのelement
もう少し役立つはずです:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
3番目の列element_id
カバーインデックスにする場合にのみ役立ちます 。クエリがテーブルelement
からさらに列を取得する場合 、インデックスに列を追加するか、element_id
を削除することをお勧めします 。どちらかが速くなります。
マテリアライズドビュー
場合 テーブルは更新をほとんどまたはまったく受信せず、すべてのペアの事前計算されたセットを提供するマテリアライズドビュー(action_id, element_id)
同じカテゴリを共有すると、これは超高速になります 。 (action_id, element_id)
を作成します (この順序で)主キー。