web-dev-qa-db-ja.com

ビューのクエリでWHERE句がプッシュダウンされないのはなぜですか?

Postgres 9.4では、次のクエリを頻繁に実行しています。

SELECT DISTINCT ON(recipient) * FROM messages
LEFT JOIN identities ON messages.recipient = identities.name
WHERE timestamp BETWEEN timeA AND timeB
ORDER BY recipient, timestamp DESC;

そこで、ビューを作成することにしました。

CREATE VIEW myView AS SELECT DISTINCT ON(recipient) * FROM messages
LEFT JOIN identities ON messages.recipient = identities.name
ORDER BY recipient, timestamp DESC;

SELECT * FROM myView WHERE timestamp BETWEEN timeA AND timeBのようにビューをクエリすると、パフォーマンスが大幅に低下することに気づきました。

両方のクエリでEXPLAIN ANALYZEを実行したところ、2番目のケースのデータベースがすべてのレコードを表示し、左結合を実行してからWHERE句を適用していることがわかりました。つまり、WHERE句はビューのクエリにプッシュダウンされません。また、ビューからORDER BYを削除しようとしましたが、それでもデータベースは、フィルターされたセットではなく、完全なデータに対してLEFT JOINを実行します。

この動作の理由は何ですか?ビューを使用するときに同等のパフォーマンスを得る方法はありますか?

3
NumberFour

このような関数を作成できます。

CREATE OR REPLACE FUNCTION public.get_messages_by_timestamp (
  time_a timestamp,
  time_b timestamp
)
RETURNS TABLE (
  recipient varchar,
  "timestamp" timestamp
) AS
$$
BEGIN
  RETURN QUERY
    SELECT DISTINCT ON (m.recipient) 
        m.recipient,
        m."timestamp"
      FROM messages m
      LEFT JOIN identities i ON m.recipient = i.name
      WHERE 
        m."timestamp" BETWEEN time_a AND time_b
      ORDER BY 
        m.recipient,
        m."timestamp" DESC;
END;
$$
LANGUAGE 'plpgsql';

次に、テーブルのような関数を使用できます

  SELECT *
         FROM get_messages_by_timestamp('2015-01-01', '2015-01-02')
6
Sahap Asci