Finally successful attempt
My other idea - as per comment:
What happens if you remove the LIMIT
clause for the case where no role is found? I have a suspicion that it will result in the fast plan - making LIMIT
the culprit here.
You may be able to solve your problem by pushing down your query into a subquery and applying the LIMIT
only to the outer query (untested):
SELECT *
FROM (
SELECT *
FROM "Roles" AS r
JOIN "Users" AS u ON u."RoleId" = r."Id"
JOIN "PaymentOrders" AS po ON po."UserId" = u."Id"
JOIN "Payments" AS p ON p."PaymentOrderId" = po."Id"
WHERE r."Name" = 'Moses'
) x
LIMIT 1000;
As per comment: @Davita tested and ruled out this workaround. @Kevin's answer later clarified why the workaround failed: use a CTE instead of the subquery.
Or check for existence of a role, before you employ the big query to eliminate the bad case.
This leaves questions for PostgreSQL concerning the optimization of queries with LIMIT
.
There have been a number of recent bug reports concerning query plans with LIMIT
. I quote Simon Riggs commenting on one of these reports here:
Very bad plans with LIMIT are frequent. This is bad for us because adding LIMIT usually/is supposed to make queries faster, not slower.
We need to do something.
First attempt with no success
I missed that @Craig already mentioned join_collapse_limit
in the comments. So that was of limited use:
Does reordering the JOIN
clauses have any effect?
SELECT *
FROM "Roles" AS r
JOIN "Users" AS u ON u."RoleId" = r."Id"
JOIN "PaymentOrders" AS po ON po."UserId" = u."Id"
JOIN "Payments" AS p ON p."PaymentOrderId" = po."Id"
WHERE r."Name" = 'Moses'
LIMIT 1000
Related: you did not by chance mess with the setting of join_collapse_limit
or geqo_threshold
?
Very low setting might prevent the planner from reordering your JOIN
clauses, which might explain your problem.
If that does not solve the case, I would try to create an index on "Roles"(Name)
. Not that this makes any sense with only 15 rows, but I would try to eliminate the suspicion that invalid statistics or cost parameters (or even a bug) make the planner believe the sequential scan on "Roles" to be more expensive than it is.