为了简化案例,我们假设有以下 3 个表
A(a_id), B(b_id,val_b), C(a_id,b_id,val_c)
我需要从 B 和 C 中找到所有具有某些值对的 a_id。示例查找所有具有记录的 a_id (val_b='1' and val_c='2' and B.b_id=C.b_id) AND (val_b='3 ' and val_c='4' and B.b_id=C.b_id) AND ...
select A.a_id
from A
where (A.a_id in
(select C.a_id
from B, C
where B.b_id=C.b_id and B.val_b='1' and C.val_c='2') and
A.a_id in
(select C.a_id
from B, C
where B.b_id=C.b_id and B.val_b='3' and C.val_c='4') and
A.a_id in
(select C.a_id
from B, C
where B.b_id=C.b_id and B.val_b='5' and C.val_c='6'));
我注意到的是,通过添加更多 (val_b,val_c) 附加对 postgres 需要大量时间来执行查询。请注意,id、val_b 和 val_c 都有索引。
有没有办法优化查询?尝试了显式内部连接,但无助于提高性能。
提前致谢
更多信息:
- postgres 版本 8.2.4
- 只有一对标准在 77.621 毫秒内运行
- 使用 2 对标准 - 151.588 毫秒
有 3 对标准 - 49483.979 毫秒 <-- 性能火花疯狂
请注意,单独的子查询本身在 ~62ms 下运行。
更新:
Vladimir Baranov 下面建议的两个单独的 INTERSECT 查询版本和 Clodoaldo Neto 使用 bool_or 聚合函数的具有子句的版本都表现得更好。谢谢 !
但是,问题仍然存在,为什么 postgres 8.2 具有这样的性能火花,原始查询从 3 对标准开始?
顺便说一句,我注意到弗拉基米尔·巴拉诺夫(Vladimir Baranov)的第一个建议是用干净的连接重写查询也产生了同样的火花。见下文:
SELECT A.a_id
FROM
A
INNER JOIN (SELECT C.a_id FROM B INNER JOIN C ON B.b_id=C.b_id WHERE B.val_b='1' and C.val_c='2') Set1 ON Set1.a_id = A.a_id
INNER JOIN (SELECT C.a_id FROM B INNER JOIN C ON B.b_id=C.b_id WHERE B.val_b='3' and C.val_c='4') Set2 ON Set2.a_id = A.a_id
INNER JOIN (SELECT C.a_id FROM B INNER JOIN C ON B.b_id=C.b_id WHERE B.val_b='5' and C.val_c='6') Set3 ON Set3.a_id = A.a_id
;
使用 3 个集合时,查询运行得非常快,但是一旦添加另外 3-4 个集合,查询性能就会下降到 ~30-40 秒。