Há muitas linhas na tabela "logs" (o Request A FROM).
A solicitação A é rápida e a solicitação B é rápida.
Juntos, o Pedido A WHERE IN O Pedido B é muito longo. Isso é normal?
A solicitação A é muito rápida:
--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";
A solicitação B é muito rápida:
--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"
O resultado de B é a mesma lista de números do pedido A WHERE IN.
Substituindo o pedido A WHERE IN pelo pedido B, torna-se muito lento.
Postgres: 9.5.6
Plano de consulta para a solicitação A:
Sim, isso é bastante comum ao elaborar consultas. No primeiro caso, a
IN(...)
cláusula tem apenas um punhado de constantes. O planejador sabe exatamente quantos valores e com que frequência eles estão na tabela, então ele tem uma boa chance de encontrar um plano de execução ideal (neste caso, uma varredura de índice).Quando o interior desta
IN (...)
cláusula é substituído por uma subconsulta, o planejador pode estimar erroneamente o número de valores que essa subconsulta produzirá, ou sua frequência, ou ambos, especialmente se a subconsulta for complexa, e, portanto, pode escolher um valor não plano ideal em comparação com quando há uma lista de constantes dentroIN (...)
.