【发布时间】:2015-02-23 21:57:58
【问题描述】:
为了简化案例,我们假设有以下 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 秒。
【问题讨论】:
-
这些值实际上是字符串。我在这个例子中只使用了数值,但可以是最长 255 个字符的任何字符串。
-
8.2?真的吗? 8.x 是no longer maintained(=支持)。您应该尽快升级到 9.4。
标签: sql postgresql database-performance in-subquery