2016-04-30 8 views
1

PostgreSQLがクエリを簡略化する方法を理解しようとしています。つまり、2つのテーブル(「tb_thing」と「tb_thing_template」)を持ち、それぞれがテンプレートを指し、このようなクエリ:選択された列に基づいて簡素化をクエリする

EXPLAIN SELECT 
    tb_thing.id 
FROM 
    tb_thing, 
    tb_thing_template 
WHERE 
    tb_thing_template.id = tb_thing.template_id 
; 

これが結果です:私はちょうど「tb_thing_template」から「tb_thing」とnothingから一つのフィールドを選択していた場合でも

        QUERY PLAN          
--------------------------------------------------------------------------------- 
Hash Join (cost=34.75..64.47 rows=788 width=4) 
    Hash Cond: (tb_thing.template_id = tb_thing_template.id) 
    -> Seq Scan on tb_thing (cost=0.00..18.88 rows=788 width=8) 
    -> Hash (cost=21.00..21.00 rows=1100 width=4) 
     -> Seq Scan on tb_thing_template (cost=0.00..21.00 rows=1100 width=4) 

プランナーは、2つのテーブルを結合しています。私はプランナーが実際に "tb_thing_template"テーブルに参加する必要はないことを理解するのに十分なほどスマートであることを期待していました。なぜなら、私はそこから何も選択していないからです。

どうして結合するのですか?クエリが計画されているときに列の選択が考慮されないのはなぜですか?

ありがとうございます!

+1

しかし、**あなたは**参加しています。 **暗黙的な結合**クエリプランナーは、実行依頼したことを行っています。 – e4c5

答えて

1

意味的には、クエリと単純なSELECT tb_thing.id FROM tb_thingは同じではありません。

たとえば、テーブルtb_thing_templateには、idの値がtb_thing.template_idの4つの行があるとします。クエリの結果には、同じtb_thing.idの4つの行があります。逆にtb_thing.template_idtb_thing_template.idに存在しない場合、その行は出力されません。 tb_thing_template.idPRIMARY KEY(とてもユニーク)であり、tb_thing.template_idPRIMARY KEYためのただ1つの行にそのidからFOREIGN KEYので、1場合

のみ:1の関係、両方のクエリは、意味的に同じです。 PK-FK関係でより典型的な1:Nの関係でさえ、意味的な意味での結合が必要です。しかし、プランナーは、関係が1:1であるかどうかを知る方法がないため、結合を取得します。

しかし、クエリプランナーを偽装しようとしないでください。それはスマートですが、必ずしもあなたよりもスマートではありません。

+0

テーブルの定義を忘れてしまいました。これは、関連するフィールドだけを保持しています。CREATE TABLE tb_thing_template(id serial PRIMARY KEY); CREATE TABLE tb_thing(IDシリアルPRIMARY KEY、template_id integer REFERENCES tb_thing_template NOT NULL); 最初の条件を理解していますが、「各PRIMARY KEYに対して1行だけで」とはどういう意味ですか?ありがとう。 – pleg

+0

これは1:1の関係です。更新された回答をご覧ください。 – Patrick

関連する問題