表“日志”(请求 A FROM)中有很多行。
请求 A 很快,请求 B 很快。
放在一起,Request A WHERE IN Request B 很长。这正常吗?
请求 A 非常快:
--request A
SELECT "rid", max("createdAt") as "createdAt"
FROM "logs"
WHERE "rid" IN (17,71,196,187,111,86,108,81,54,184,245,27,118,100,175,136,130,67,45)
GROUP BY "rid";
请求 B 非常快:
--request B
SELECT "dr"."rid"
FROM (
SELECT *
FROM (
SELECT "eid", "tid", count(*) over (partition by "eid", "tid") count, id as "rid"
FROM rs
WHERE "deletedAt" is NULL
) "nr"
WHERE count > 1
) "dr"
INNER JOIN teams ON teams.id = "dr"."tid"
INNER JOIN projects ON projects.id = teams."pid"
ORDER BY "eid", "tid"
B 的结果与请求 A WHERE IN 中的数字列表相同。
用请求B替换请求A WHERE IN,它变得非常慢。
Postgres:9.5.6
是的,这在详细说明查询时相当常见。在第一种情况下,
IN(...)
子句只有几个常量。计划器确切地知道表中有多少值以及它们的频率,因此它很有可能找到最佳执行计划(在本例中为索引扫描)。当这个
IN (...)
子句的内部被一个子查询替换时,计划器可能会错误估计这个子查询将产生的值的数量,或者它们的频率,或者两者兼而有之,特别是如果子查询很复杂,所以它可能会选择一个非与内部有常量列表时相比的最佳计划IN (...)
。