2016-08-31 15 views
0

インデックスを持つテーブルがあります(列A、列B)。そして、私は次のようなクエリを実行しています:INでpostgresクエリが非常に遅い

SELECT * FROM table WHERE (A, B) IN ((a_1, b_1), (a_2, b_2), ..., (a_5000, b_5000)) 

このクエリは非常に遅いです! 計画は次のようになります。

Bitmap Heap Scan on table 
    Recheck Cond: (((A = a_1) AND (B = b_1)) OR ((A = a_2) AND (B = b_2)) OR ... 
    -> BitmapOr 
     -> Bitmap Index Scan on idx 
       Index Cond: ((A = a_1) AND (B = b_1)) 
     -> Bitmap Index Scan on idx 
       Index Cond: ((A = a_2) AND (B = b_2)) 
     ...(5000 other Bitmax Index Scan) 

の代わりに5000個の値を持つ1回のインデックススキャンを行って、Postgresは、クエリが非常に遅くなる理由を説明している、一度に一つの値を持つ5000インデックス・スキャンをやっているようです。

SELECT * FROM table WHERE A IN (a_1, ..., a_5000) 

結果を取得した後、アプリ(パイソン)内側列Bをフィルタリング:

実際には次のようにいろいろ書いを行う方法速いです。

妥当な実行時間でpostgresによって結果がフィルタリングされているのが本当に好きです。回避策はありますか? CTEに参加

答えて

1

試してみてください。

with value_list (a,b) as (
    values 
     (a_1, b_1), 
     (a_2, b_2), ..., 
     (a_5000, b_5000) 
) 
select * 
from table t 
    join value_list v on (t.a, t.b) = (v.a, v.b); 

は(これはあなたが値のリストには重複がないと仮定し)

+0

興味深いです。何が違いますか? – zerkms

+0

@zerkms:理論(希望)は、各値に対して1回のスキャンではなく、すべての値に対して1回のインデックススキャンを実行するようオプティマイザを欺くことです。 –

+0

それは動作します!プランナーは実際にはただ1つのhashjoinを使用します。私はプランナーが最初のクエリを処理するほどスマートではありませんが、それは変です。 –

関連する問題