Columns correlation and adaptive query optimization

From: Konstantin Knizhnik <k(dot)knizhnik(at)postgrespro(dot)ru>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Columns correlation and adaptive query optimization
Date: 2019-10-14 16:43:10
Message-ID: 196f1e1a-5464-ed07-ab3c-0c9920564af7@postgrespro.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi hackers,

Errors in selectivity estimations is one of the main reason of bad plans
generation by Postgres optimizer.
Postgres estimates selectivity based on the collected statistic
(histograms).
While it is able to more or less precisely estimated selectivity of
simple predicate for particular table,
it is much more difficult to estimate selectivity for result of join of
several tables and for complex predicate consisting of several
conjuncts/disjuncts
accessing different columns.

Postgres is not able to take in account correlation between columns
unless correspondent multicolumn statistic is explicitly created.
But even if such statistic is created, it can not be used in join
selectivity estimation.

The problem with adjusting selectivity using machine learning based on
the results of EXPLAIN ANALYZE was address in AQO project:

https://github.com/postgrespro/aqo

There are still many issues with proposed AQO approach (for example, it
doesn't take in account concrete constant values).
We are going  to continue its improvement.

But here I wan to propose much simpler patch which allows two things:
1. Use extended statistic in estimation of join selectivity
2. Create on demand multicolumn statistic in auto_explain extension if
there is larger gap between real and estimated number of tuples for the
concrete plan node.

create table inner_tab(x integer, y integer);
create table outer_tab(pk integer primary key, x integer, y integer);
create index on inner_tab(x,y);
insert into outer_tab values (generate_series(1,100000),
generate_series(1,100000), generate_series(1,100000)*10);
insert into inner_tab values (generate_series(1,1000000)/10,
generate_series(1,1000000)/10*10);
analyze inner_tab;
analyze outer_tab;

Without this patch:
explain select * from outer_tab join inner_tab using(x,y) where pk=1;
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.72..16.77 rows=1 width=12)
   ->  Index Scan using outer_tab_pkey on outer_tab (cost=0.29..8.31
rows=1 width=12)
         Index Cond: (pk = 1)
   ->  Index Only Scan using inner_tab_x_y_idx on inner_tab
(cost=0.42..8.45 rows=1 width=8)
         Index Cond: ((x = outer_tab.x) AND (y = outer_tab.y))
(5 rows)

With this patch:

load 'auto_explain';
set auto_explain.log_min_duration=0;
set auto_explain.add_statistics_threshold=10.0;
set auto_explain.log_analyze=on;
select * from outer_tab join inner_tab using(x,y) where pk=1;
analyze inner_tab;
analyze outer_tab;

explain select * from outer_tab join inner_tab using(x,y) where pk=1;
                                           QUERY PLAN
------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.72..32.79 rows=10 width=12)
   ->  Index Scan using outer_tab_pkey on outer_tab (cost=0.29..8.31
rows=1 width=12)
         Index Cond: (pk = 1)
   ->  Index Only Scan using inner_tab_x_y_idx on inner_tab
(cost=0.42..24.38 rows=10 width=8)
         Index Cond: ((x = outer_tab.x) AND (y = outer_tab.y))
(5 rows)

As you can see now estimation of join result is correct (10).

I attached two patches: one for using extended statistic for join
selectivity estimation and another for auto_explain to implicitly add
this extended statistic on demand.

--
Konstantin Knizhnik
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Attachment Content-Type Size
join_selectivity.patch text/x-patch 3.7 KB
auto_explain.patch text/x-patch 9.0 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeremy Finzel 2019-10-14 19:42:51 Re: BRIN index which is much faster never chosen by planner
Previous Message Tomas Vondra 2019-10-14 16:35:38 Re: BUG #16045: vacuum_db crash and illegal memory alloc after pg_upgrade from PG11 to PG12