所以我有两个表,A
和B
。
A
有一个主键id
。
B
实际上是A
中条目的列表。因此B
具有外键id
,但每个id
可能有多行。
我想运行一个查询,获取一行A
以及B
中的所有相应行。
现在我正在使用INNER JOIN
执行此操作,但我关注性能 - A
中的条目在输出中的每一行上都是重复的,以便与{{1}对应}。
以下是一个例子:
B
A
id | blah
1 | x
2 | y
另请注意,B
id | foo
1 | m
1 | n
1 | o
2 | p
可能包含许多包含相关数据的列,而不只是一列B
列。
我希望能够运行foo
来SELECT
,id = 1
来自blah = x
和A
,foo = m
来自foo = n
的{}和foo = o
。但是除非我过度思考它,否则似乎返回以下内容的连接效率会非常低,因为B
可能会非常大,反复重复(这也有点难以解析)服务器端)。
x
我觉得这是一个足够普遍的程序,它应该有一个有效的查询,但我无法清楚地得到足够的措辞,以便在网上找到任何有用的东西:(
我正在使用PostgreSQL 10,但我想这个命令可能与其他查询语言类似。
答案 0 :(得分:3)
我怀疑担心加入结果中的冗余数据量是不必要的,除非您有证据表明客户端上的网络带宽或解析值是您的瓶颈。
通常,返回所有结果的单个查询(下面的选项1)最好。
你应该运行一个基准测试并比较这两件事:
简单查询:
SELECT id, a.blah, b.foo
FROM a JOIN b USING (id);
两个查询,避免了结果冗余:
SELECT a.id, a.blah
FROM a
WHERE EXISTS
(SELECT 1 FROM b
WHERE b.id = a.id);
SELECT id, b.foo
FROM a JOIN b USING (id);
所有其他方法必须更慢:
通过对b
中a
中找到的每一行IN
执行单独查询,在应用程序中执行嵌套循环连接是疯狂的。它总是会表现更差,因为必须为连接结果中的每一行支付执行数据库查询(组成查询,发送,解析和处理数据库,发回结果,解析结果)的开销。
使用第一个查询中找到的id
个user
列表发送第二个查询可能会生成需要很长时间才能解析的非常长的语句。此外,这些语句的执行效率低于连接本身。从本质上讲,它是散列连接的去优化版本。