2017-10-16 8 views
0

declarative partitioning(w00t!)を使用して、テーブルを日付範囲(1年間は私の場合)でパーティション化しています。Postgresが日付範囲パーティションをフィルタリングしないのはなぜですか?

私はテーブル - SELECT * FROM tbl WHERE date > date '2016-01-01'に対してクエリを実行すると、意図したとおりに動作します。新しいデータを含むテーブルだけがスキャンされます。

変数または関数(CURRENT_DATENOW()など)を使用して日付を指定すると、EXPLAINはすべてのパーティションをスキャンします。意図したとおりに動作し

もの:不必要なすべてのパーティションをスキャン

SELECT * FROM tbl WHERE date > date '2016-01-01' 
-- 
SELECT * FROM tbl WHERE date > '2016-01-01'::date 

もの:私は他の比較演算子と同じ振る舞いを取得

SELECT * FROM tbl WHERE date > CURRENT_DATE 
-- 
SELECT * FROM tbl WHERE date > NOW() 
-- 
SELECT * FROM tbl WHERE date > (NOW() - 365)::date 
-- 
SELECT * FROM tbl WHERE date > (SELECT (NOW()::date - 365)::date AS d) 
-- Even CTEs are no dice: 
WITH a AS (SELECT CURRENT_DATE AS d) 
SELECT * FROM tbl, a WHERE date > a.d 
-- Same with JOINs 
SELECT w.* 
FROM (CURRENT_DATE - 365 as d) a 
LEFT JOIN wtf w ON w.date > a.d 

..etc

から=を、 <など

私はフィールド上にidxは必要ないと言っています(私はとにかくそうしません)。私はちょうどのために1つを追加し、それは役に立たなかった。

なぜこのようなことが起こりますか(単純なクエリに複雑化を加えることなく)できればどうしたらいいですか?

+0

してください** [EDIT]にRETURNS setof textRETURNS setof tblSELECT...を変更することによって、あなたの質問にこれをテストし、 'CREATE TABLEを追加することができます。機能は最高っぽい選択肢であると思われます'文(すべてのインデックスを含む)と** explain(analyze、verbose)を使用して生成された実行計画**を使用します。 [**フォーマットされたテキスト**](http://stackoverflow.com/help/formatting)、[スクリーンショットなし](http://meta.stackoverflow.com/questions/285551/why-may-i-not -with-upload-on-code-on-so-asking-a-question/285557#285557) –

+2

これは、実行するまでplannerがnow()の出力を知らないためです。 – JustMe

+0

ありがとう@JustMe - これを回答として投稿して、不要なSQLとEXPLAINの出力を取り除いてこれを他の人にも役立てますか? – onwsk8r

答えて

0

これに答えるためのJustMeのおかげで、OPのコメントを参照してください。

NOW()CURRENT_TIMESTAMPFROMに関して評価されています。あなたが結合alaでフィルタリングしようとしたときに見る同じ問題WHERE join_table.a > from_table.bです。今日仮に

は1970年1月1日で、これらのクエリ

SELECT * FROM my_stuff WHERE date > NOW()::date; 
-- 
SELECT * FROM my_stuff WHERE date > '1970-01-01'::date; 

は必ずしも同一で結果セットを生成しますが、必ずしも同じ方法で評価されることはありません。

これはこれが起こっている理由です。残念ながら、それを止める簡単な方法はないようです。

CREATE OR REPLACE FUNCTION myfunc() 
    RETURNS setof tbl 
    LANGUAGE 'plpgsql' 
AS $$ 
DECLARE 
    n date := CURRENT_DATE - 365; 
BEGIN 
    RETURN query EXECUTE $a$ 
     SELECT * FROM tbl 
     WHERE date > $1; 
    $a$ using n; 
END $$; 

あなたは** EXPLAIN SELECT...

関連する問題