我试图了解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
;
结果如下:
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)
即使我只是从“tb_thing”中选择一个字段而没有从“tb_thing_template”中选择任何字段,规划人员也会加入这两个表格。我希望计划者能够聪明地弄清楚它不需要实际加入“tb_thing_template”表,因为我没有从中选择任何东西。
为什么要进行加入呢?为什么在计划查询时不考虑列选择?
谢谢!
答案 0 :(得分:1)
从语义上讲,您的查询和简单的SELECT tb_thing.id FROM tb_thing
不一样。
例如,假设表tb_thing_template
有4行,其id
值相同,也是tb_thing.template_id
。然后,您的查询结果将包含4行tb_thing.id
。相反,如果tb_thing.template_id
中不存在tb_thing_template.id
,则不会输出该行。
仅当tb_thing_template.id
为PRIMARY KEY
(如此唯一)且tb_thing.template_id
为FOREIGN KEY
id
时,每个PRIMARY KEY
只有一行{{ 1}},所以1:1关系,两个查询在语义上都是相同的。即使是在PK-FK关系中更典型的1:N关系,也需要语义意义上的连接。但是计划者无法知道这种关系是否是1:1,所以你得到了加入。
但你不应该试图欺骗查询计划器;它很聪明,但不一定比你(可能)愚蠢聪明。