Re: BUG #18423: suboptimal query plan is used when ordering by an indexed field with limit

Mao Jiayin <maojiayin@gmail.com>

From: Mao Jiayin <maojiayin@gmail.com>
To: Jeff Janes <jeff.janes@gmail.com>
Cc: pgsql-bugs@lists.postgresql.org
Date: 2024-04-07T03:32:41Z
Lists: pgsql-bugs
Thanks Jeff. This is really helpful. I agree this is not really a bug,
please feel free to close it.

If you still want to know the size of the table, it is about 6 million.

On Sat, Apr 6, 2024 at 7:25 PM Jeff Janes <jeff.janes@gmail.com> wrote:

> On Sat, Apr 6, 2024 at 5:44 PM PG Bug reporting form <
> noreply@postgresql.org> wrote:
>
>>
>> For example, our "user" table has an id primary key, an "org_id" column
>> and
>> a "disabled" column. The table has millions of rows and for each org_id
>> there is only usually a few hundred rows.
>
>
> It would be helpful to know precisely how many millions of rows.  We know
> it actually removed 596003 rows from the ordered index scan, but we don't
> know how many it thought it would need to remove.  I reckon it thought it
> would remove # in table / 837, but I don't know what that division comes
> out to, not knowing the numerator.
>
>
>>          ->  Index Scan using user_org_disabled_idx on user
>> (cost=0.43..3141.43 rows=837 width=236) (actual time=0.049..1.407 rows=166
>> loops=1)
>>
>
> So this estimate is quite wrong, 837/166 = 5.  Do you know why?  This bad
> estimate makes this plan look 5 times too expensive, and the competing one
> look 5 times too cheap, for a ratio of 25.  That is more than the current
> ratio between the two plan cost estimates, so fixing this could drive the
> difference.  (The ratio of actual times is more than 25, so there is more
> to the problem than just this, but fixing this alone should be enough to
> drive the correct choice).  So why is this estimate that bad?  Is the
> selectivity estimate of `org_id = 123456` alone that bad, or is it only
> when combined with `disabled=false`?
>
> A more robust solution is to add an index on (org_id, disabled, id).  That
> way it can combine the two strategies, jumping to just the part of the
> index it needs and then reading it already in order.  Not only will this be
> much faster than either of the two plans you show, it will also be more
> resilient to estimation errors.
>
> Anyway, these just look like well-known estimation difficulties, nothing
> which seems like an actual bug. Estimation is hard and sometimes there is
> no way to know the correct value to use until after the query is already
> underway.
>
> Cheers,
>
> Jeff
>