Hi,

Before spamming the list with reproduction examples I want to make sure the issue isn't already known.

Moving to 10.4 from 9.2 (AWS RDS but repro on local laptop as well) we've discovered that an optimizer prefers a seq scan to fully analyzed consistent BRIN index, ending up with a query that is 4.8s long on seqscan vs 56ms when forcing use of BRIN (85 times difference). The size of the dataset is millions of rows and with extremely high probability the rows are naturally clustered on BRIN index column.

Anybody observed anything like that?

========================================================
schema0=# SET enable_seqscan=false;
SET
schema0=# EXPLAIN (analyze, verbose, costs, buffers) SELECT data, count(*) OVER() AS full_count FROM schema0_lab.data_table WHERE segment = 'pb1'
                    AND (data->>'tradeDate')::numeric >= '1531267200'
                    AND (data->>'tradeDate')::numeric <= '1531353600'
                    AND data->>'tradeStatus' = 'Replaced'
                    ORDER BY (data->>'tradeDate')::numeric
                    DESC;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=617851.03..617851.24 rows=84 width=1219) (actual time=55.765..55.794 rows=611 loops=1)    Output: data, (count(*) OVER (?)), (((data ->> 'tradeDate'::text))::numeric)
   Sort Key: (((data_table.data ->> 'tradeDate'::text))::numeric) DESC
   Sort Method: quicksort  Memory: 1256kB
   Buffers: shared hit=824
   ->  WindowAgg  (cost=1231.98..617848.34 rows=84 width=1219) (actual time=52.688..55.068 rows=611 loops=1)          Output: data, count(*) OVER (?), ((data ->> 'tradeDate'::text))::numeric
         Buffers: shared hit=824
         ->  Gather  (cost=1231.98..617846.66 rows=84 width=1179) (actual time=8.247..51.804 rows=611 loops=1)
               Output: data
               Workers Planned: 2
               Workers Launched: 2
               Buffers: shared hit=824
               ->  Parallel Bitmap Heap Scan on schema0_lab.data_table  (cost=231.98..616838.26 rows=35 width=1179) (actual time=3.850..46.704 rows=204 loops=3)
                     Output: data
                     Recheck Cond: ((((data_table.data ->> 'tradeDate'::text))::numeric >= '1531267200'::numeric) AND (((data_table.data ->> 'tradeDate'::text))::numeric <= '1531353600'::numeric))
                     Rows Removed by Index Recheck: 4404
                     Filter: (((data_table.segment)::text = 'pb1'::text) AND ((data_table.data ->> 'tradeStatus'::text) = 'Replaced'::text))
                     Heap Blocks: lossy=794
                     Buffers: shared hit=2334
                     Worker 0: actual time=3.572..44.145 rows=236 loops=1
                       Buffers: shared hit=749
                     Worker 1: actual time=0.326..45.184 rows=212 loops=1
                       Buffers: shared hit=761
                     ->  Bitmap Index Scan on tradedate_idx (cost=0.00..231.96 rows=3377106 width=0) (actual time=4.500..4.500 rows=23040 loops=1)                            Index Cond: ((((data_table.data ->> 'tradeDate'::text))::numeric >= '1531267200'::numeric) AND (((data_table.data ->> 'tradeDate'::text))::numeric <= '1531353600'::numeric))
                           Buffers: shared hit=30
 Planning time: 0.246 ms
 Execution time: 56.209 ms
(29 rows)

schema0=# SET enable_seqscan=true;
SET
schema0=# EXPLAIN (analyze, verbose, costs, buffers) SELECT data, count(*) OVER() AS full_count FROM schema0_lab.data_table WHERE segment = 'pb1'
                    AND (data->>'tradeDate')::numeric >= '1531267200'
                    AND (data->>'tradeDate')::numeric <= '1531353600'
                    AND data->>'tradeStatus' = 'Replaced'
                    ORDER BY (data->>'tradeDate')::numeric
                    DESC;
QUERY PLAN

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------
 Sort  (cost=617619.05..617619.26 rows=84 width=1219) (actual time=4823.081..4823.106 rows=611 loops=1)    Output: data, (count(*) OVER (?)), (((data ->> 'tradeDate'::text))::numeric)
   Sort Key: (((data_table.data ->> 'tradeDate'::text))::numeric) DESC
   Sort Method: quicksort  Memory: 1256kB
   Buffers: shared hit=839 read=187353
   ->  WindowAgg  (cost=1000.00..617616.36 rows=84 width=1219) (actual time=4820.005..4822.390 rows=611 loops=1)          Output: data, count(*) OVER (?), ((data ->> 'tradeDate'::text))::numeric
         Buffers: shared hit=839 read=187353
         ->  Gather  (cost=1000.00..617614.68 rows=84 width=1179) (actual time=3.262..4819.362 rows=611 loops=1)
               Output: data
               Workers Planned: 2
               Workers Launched: 2
               Buffers: shared hit=839 read=187353
               ->  Parallel Seq Scan on schema0_lab.data_table (cost=0.00..616606.28 rows=35 width=1179) (actual time=6.135..4814.826 rows=204 loops=3)
                     Output: data
                     Filter: (((data_table.segment)::text = 'pb1'::text) AND ((data_table.data ->> 'tradeStatus'::text) = 'Replaced'::text) AND (((data_table.data ->> 'tradeDate'::text))::numeric >= '1531267200'::numeric) AND (((data_table.data
 ->> 'tradeDate'::text))::numeric <= '1531353600'::numeric))
                     Rows Removed by Filter: 1125498
                     Buffers: shared hit=2400 read=561439
                     Worker 0: actual time=11.414..4812.744 rows=220 loops=1
                       Buffers: shared hit=775 read=187333
                     Worker 1: actual time=4.249..4813.264 rows=220 loops=1
                       Buffers: shared hit=786 read=186753
 Planning time: 0.232 ms
 Execution time: 4823.412 ms
(24 rows)

schema0=# \d schema0_lab.data_table

                                         Table "schema0_lab.data_table"
   Column   |          Type          | Collation | Nullable |                     Default
------------+------------------------+-----------+----------+--------------------------------------------------
 id         | integer                |           | not null | nextval('schema0_lab.data_table_id_seq'::regclass)
 address    | character varying(128) |           | not null |
 segment    | character varying(128) |           | not null |
 data       | jsonb                  |           | not null |
Indexes:
    "data_table_pkey" PRIMARY KEY, btree (id)
    "tradedate_idx" brin (((data ->> 'tradeDate'::text)::numeric)) WITH (autosummarize='true')

--
Arcadiy Ivanov
arca...@gmail.com | @arcivanov | https://ivanov.biz
https://github.com/arcivanov

Reply via email to