2

WITHPostgres が句を含むクエリを実行する方法について (おそらく) 基本的な質問があります。WITH余分なテーブルを句に含めると、実際にクエリが遅くなるかどうか疑問に思っています。つまり、WITH句で作成された「一時」テーブルが句の外で呼び出されないWITH場合、その「一時」テーブルは実際に作成されますか?

WITH最初の例では、句を使用して作成された 2 つの「一時」テーブルを結合しています。

--Example 1
WITH temp1 as (
SELECT * from table_1
),
temp2 as (
select * from table_2
)
select * 
from temp1
join temp2;

2 番目の例では、まったく同じクエリを実行していますが、WITH句で無関係なテーブル "temp3" が作成されています。

--Example 2
WITH temp1 as (
SELECT * from table_1
),
temp2 as (
select * from table_2
),
temp3 as (
select * from table_3
)
select * 
from temp1
join temp2;

これら 2 つのクエリにパフォーマンスの違いはありますか? が巨大なテーブルの場合table_3、例 2 と例 1 のクエリは遅くなりますか? そうでない場合、なぜですか?

クエリ時間には影響しないようです。その理由は今でも気になるところですが…

4

2 に答える 2

6

Explain を使用して、クエリ オプティマイザーがクエリを処理する方法を示すことができます。

http://www.postgresql.org/docs/9.2/static/sql-explain.html

上記の場合、PSQL は temp3 が使用されていないことを確認し、含めないようにする必要があります。

上記の例を 1 つの my dbs で使用します。

explain with temp1 as (select * from cidrs), temp2 as (select * from contacts), temp3 as ( select * from accounts )  select * from temp1 join temp2 on temp1.id = temp2.id;
                             QUERY PLAN
---------------------------------------------------------------------
 Hash Join  (cost=22.15..25.44 rows=20 width=4174)
   Hash Cond: (temp1.id = temp2.id)
   CTE temp1
     ->  Seq Scan on cidrs  (cost=0.00..11.30 rows=130 width=588)
   CTE temp2
     ->  Seq Scan on contacts  (cost=0.00..10.20 rows=20 width=3586)
   ->  CTE Scan on temp1  (cost=0.00..2.60 rows=130 width=588)
   ->  Hash  (cost=0.40..0.40 rows=20 width=3586)
         ->  CTE Scan on temp2  (cost=0.00..0.40 rows=20 width=3586)
(9 rows)

temp3 について言及されていないことに気付くでしょう。あなたの編集に答える際に、クエリ時間に影響を与えない理由について、オプティマイザーはそれが使用されておらず、計算に煩わされていないことを確認するのに十分スマートです。したがって、それがオプティマイザーである理由です。

于 2013-12-30T16:07:26.217 に答える
5

あなたはすでに@Doonから主な答えを得ています。

パフォーマンスに関心があるため、サブクエリは通常、ほとんどの場合CTE よりも高速であることに注意してください。共通テーブル式 (WITH クエリ) は、最適化の障壁となります。詳細については、pgsql-performance に関するこのスレッドを参照してください。

CTE を使用する ...

  • .. サブクエリが複数の場所で使用されている場合は、実行の繰り返しを回避します。
  • .. オプティマイザーが何らかの理由でサブクエリとメインクエリを結合しようとするのを防ぐため (パフォーマンス、関数からの副作用への影響を回避)。
  • .. 複雑なクエリを分割する (可読性、保守性)
  • .. RECURSIVE クエリの場合。
于 2013-12-30T17:49:45.480 に答える