po 23. 8. 2021 v 18:44 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

> Hi
>
> The customer reports a very slow query. I have a reproducer script. The
> dataset is not too big
>
> postgres=# \dt+
>                              List of relations
> ┌────────┬───────┬───────┬───────┬─────────────┬────────────┬─────────────┐
> │ Schema │ Name  │ Type  │ Owner │ Persistence │    Size    │ Description │
> ╞════════╪═══════╪═══════╪═══════╪═════════════╪════════════╪═════════════╡
> │ public │ f_dep │ table │ pavel │ permanent   │ 8192 bytes │             │
> │ public │ f_emp │ table │ pavel │ permanent   │ 1001 MB    │             │
> │ public │ f_fin │ table │ pavel │ permanent   │ 432 kB     │             │
> │ public │ qt    │ table │ pavel │ permanent   │ 1976 kB    │             │
> │ public │ qtd   │ table │ pavel │ permanent   │ 87 MB      │             │
> └────────┴───────┴───────┴───────┴─────────────┴────────────┴─────────────┘
> (5 rows)
>
> and the query is not too complex
>
> SELECT
>      sub.a_121,
>      count(*)
> FROM (
>         SELECT
>               f_fin.dt_business_day_id AS a_1056,
>               f_dep.description_id AS a_121,
>               f_emp.employee_id_id AS a_1327
>         FROM  f_emp
>         INNER JOIN f_dep ON
>                 ( f_emp.department_id_id = f_dep.id )
>         INNER JOIN f_fin ON
>                 ( f_emp.business_day_date_id = f_fin.id )
>         GROUP BY 1, 2, 3
>       ) AS sub
> INNER JOIN qt ON
>         ( sub.a_1056 = qt.tt_1056_1056_b )
> LEFT OUTER JOIN qtd AS qt_2 ON
>         ( ( qt.tt_1056_1056_b = qt_2.a_1056 )
>         AND ( sub.a_121 = qt_2.a_121 )
>         AND ( sub.a_1327 = qt_2.a_1327 ) )
> LEFT OUTER JOIN qtd AS qt_3 ON
>         ( ( qt.tt_1056_1056_a = qt_3.a_1056 )
>         AND ( sub.a_121 = qt_3.a_121 )
>         AND ( sub.a_1327 = qt_3.a_1327 ) )
> GROUP BY 1;
>
> By default I get a good plan, and the performance is ok
> https://explain.depesz.com/s/Mr2H (about 16 sec). Unfortunately, when I
> increase work_mem, I get good plan with good performance
> https://explain.depesz.com/s/u4Ff
>
> But this depends on index only scan. In the production environment, the
> index only scan is not always available, and I see another plan (I can get
> this plan with disabled index only scan).
>
> Although the cost is almost the same, the query is about 15x slower
> https://explain.depesz.com/s/L6zP
>
> │ HashAggregate  (cost=1556129.74..1556131.74 rows=200 width=12) (actual
> time=269948.878..269948.897 rows=64 loops=1)
>                 │
> │   Group Key: f_dep.description_id
>
>               │
> │   Batches: 1  Memory Usage: 40kB
>
>              │
> │   Buffers: shared hit=5612 read=145051
>
>              │
> │   ->  Merge Left Join  (cost=1267976.96..1534602.18 rows=4305512
> width=4) (actual time=13699.847..268785.500 rows=4291151 loops=1)
>                      │
> │         Merge Cond: ((f_emp.employee_id_id = qt_3.a_1327) AND
> (f_dep.description_id = qt_3.a_121))
>                          │
> │         Join Filter: (qt.tt_1056_1056_a = qt_3.a_1056)
>
>              │
> │         Rows Removed by Join Filter: 1203659495
>
>               │
> │         Buffers: shared hit=5612 read=145051
>
>              │
>
>             .....
>
>                         │
> │         ->  Sort  (cost=209977.63..214349.77 rows=1748859 width=12) (actual
> time=979.522..81842.913 rows=1205261892 loops=1)
>              │
> │               Sort Key: qt_3.a_1327, qt_3.a_121
>
>               │
> │               Sort Method: quicksort  Memory: 144793kB
>
>              │
> │               Buffers: shared hit=2432 read=8718
>
>              │
> │               ->  Seq Scan on qtd qt_3  (cost=0.00..28638.59
> rows=1748859 width=12) (actual time=0.031..284.437 rows=1748859 loops=1)
> │                     Buffers: shared hit=2432 read=8718
>
> The sort of qtd table is very fast
>
> postgres=# explain analyze select * from qtd order by a_1327, a_121;
>
> ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
> │                                                      QUERY PLAN
>                                              │
>
> ╞══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
> │ Sort  (cost=209977.63..214349.77 rows=1748859 width=27) (actual
> time=863.923..1111.213 rows=1748859 loops=1)         │
> │   Sort Key: a_1327, a_121
>                                              │
> │   Sort Method: quicksort  Memory: 199444kB
>                                             │
> │   ->  Seq Scan on qtd  (cost=0.00..28638.59 rows=1748859 width=27)
> (actual time=0.035..169.385 rows=1748859 loops=1) │
> │ Planning Time: 0.473 ms
>                                              │
> │ Execution Time: 1226.305 ms
>                                              │
>
> └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
> (6 rows)
>
> but here it returns 700x lines more and it is 70 x slower. Probably it is
> because something does rescan. But why? With index only scan, I don't see
> any indices of rescan.
>
> Is it an executor or optimizer bug? Or is it a bug? I tested this
> behaviour on Postgres 13 and on the fresh master branch.
>

 When I increase cpu_operator_cost, then I got workable plan although I use
high work mem

https://explain.depesz.com/s/jl4v

The strange thing of this issue is possible unhappy behaviour although the
estimation is very well

Regards

Pavel


> Regards
>
> Pavel
>
>

Reply via email to