2017-09-11 8 views
2

このようなクエリでは、すべての行がbig_tableから、または実際に必要な行から読み取られますか?Postgres CTEは必ずしもすべての行を読み込む必要はありませんか?

WITH tmp AS (SELECT * FROM big_table) 
SELECT * FROM 
    small_table st 
JOIN tmp ON tmp.Id = st.BigTableId 
WHERE st.Id = 45 

サブセレクトの方が優れていますか?

SELECT * FROM 
    small_table st 
JOIN (SELECT * FROM big_table) as tmp ON tmp.Id = st.BigTableId 
WHERE st.Id = 45 

私はコストが悪化した性能であれば、それはWITHを使用して、もう少し読みやすいクエリを記述することは可能ですが、ではないことを好みます。

答えて

2

CTEのクエリは自律的に実行されます(連続クエリの条件なし)。質問に記載されているケースでは、CTEのクエリは他のものよりもはるかに遅くなります。

疑わしい場合には、EXPLAIN ANALYZEを使用してください。あなたは次のような計画を立てるべきです。

CTE(ビッグテーブルは、それらのすべてがCTEにスキャンされます、100000行を持っている)で

Hash Join (cost=1580.96..4269.53 rows=565 width=12) (actual time=10.349..42.718 rows=1 loops=1) 
    Hash Cond: (tmp.id = st.bigtableid) 
    CTE tmp 
    -> Seq Scan on big_table (cost=0.00..1572.65 rows=112965 width=4) (actual time=0.011..11.813 rows=100000 loops=1) 
    -> CTE Scan on tmp (cost=0.00..2259.30 rows=112965 width=4) (actual time=0.013..33.524 rows=100000 loops=1) 
    -> Hash (cost=8.30..8.30 rows=1 width=8) (actual time=0.013..0.013 rows=1 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 9kB 
     -> Index Scan using small_table_pkey on small_table st (cost=0.28..8.30 rows=1 width=8) (actual time=0.009..0.009 rows=1 loops=1) 
       Index Cond: (id = 45) 

CTEがなければ:あなたはサブクエリを必要としない

Nested Loop (cost=0.57..16.61 rows=1 width=12) (actual time=0.069..0.071 rows=1 loops=1) 
    -> Index Scan using small_table_pkey on small_table st (cost=0.28..8.29 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=1) 
     Index Cond: (id = 45) 
    -> Index Only Scan using big_table_pkey on big_table (cost=0.29..8.31 rows=1 width=4) (actual time=0.056..0.056 rows=1 loops=1) 
     Index Cond: (id = st.bigtableid) 
     Heap Fetches: 1 

注意を2番目のクエリ。これに自動的に最適化されます:

SELECT * 
FROM small_table st 
JOIN big_table as tmp ON tmp.Id = st.BigTableId 
WHERE st.Id = 45 
関連する問題