Thread: pg15 inherited stats expressions: cache lookup failed for statistics object

pg15 inherited stats expressions: cache lookup failed for statistics object

From
Justin Pryzby
Date:
postgres=# \set QUIET 
CREATE TABLE stxdinp (i int, j int) PARTITION BY RANGE(i);
CREATE TABLE stxdinp1 PARTITION OF stxdinp FOR VALUES FROM (1)TO(10);
INSERT INTO stxdinp SELECT generate_series(1,9)a;
CREATE STATISTICS stxdp ON i,j FROM stxdinp;
ANALYZE stxdinp;
explain SELECT i, j, COUNT(1) FROM ONLY stxdinp GROUP BY 1,2;
ERROR:  cache lookup failed for statistics object 4060843

It's evidently an issue with 269b532ae (Add stxdinherit flag to
pg_statistic_ext_data)

(gdb) bt
#0  pg_re_throw () at elog.c:1795
#1  0x000000000096578a in errfinish (filename=<optimized out>, filename@entry=0xaf0442 "extended_stats.c",
lineno=lineno@entry=2467,funcname=funcname@entry=0xaf0720 <__func__.28166> "statext_expressions_load") at elog.c:588
 
#2  0x00000000007efd07 in statext_expressions_load (stxoid=3914359, inh=<optimized out>, idx=idx@entry=0) at
extended_stats.c:2467
#3  0x0000000000913947 in examine_variable (root=root@entry=0x2b5b530, node=node@entry=0x2b88820,
varRelid=varRelid@entry=7,vardata=vardata@entry=0x7ffe5baa2f00) at selfuncs.c:5264
 
#4  0x00000000009141ae in get_restriction_variable (root=root@entry=0x2b5b530, args=args@entry=0x2b88a30,
varRelid=varRelid@entry=7,vardata=vardata@entry=0x7ffe5baa2f90, other=other@entry=0x7ffe5baa2f88, 
 
    varonleft=varonleft@entry=0x7ffe5baa2f87) at selfuncs.c:4848
#5  0x0000000000915535 in eqsel_internal (fcinfo=<optimized out>, negate=negate@entry=false) at selfuncs.c:263
#6  0x00000000009155f6 in eqsel (fcinfo=<optimized out>) at selfuncs.c:226
#7  0x000000000096a373 in FunctionCall4Coll (flinfo=flinfo@entry=0x7ffe5baa3090, collation=collation@entry=0,
arg1=arg1@entry=45462832,arg2=arg2@entry=1320, arg3=arg3@entry=45648432, arg4=arg4@entry=7) at fmgr.c:1198
 
#8  0x000000000096a92a in OidFunctionCall4Coll (functionId=<optimized out>, collation=collation@entry=0,
arg1=arg1@entry=45462832,arg2=arg2@entry=1320, arg3=arg3@entry=45648432, arg4=arg4@entry=7) at fmgr.c:1434
 
#9  0x000000000077e759 in restriction_selectivity (root=root@entry=0x2b5b530, operatorid=operatorid@entry=1320,
args=0x2b88a30,inputcollid=0, varRelid=varRelid@entry=7) at plancat.c:1880
 
#10 0x0000000000728dc9 in clause_selectivity_ext (root=root@entry=0x2b5b530, clause=0x2b889d8, clause@entry=0x2b86e88,
varRelid=varRelid@entry=7,jointype=jointype@entry=JOIN_INNER, sjinfo=sjinfo@entry=0x0, 
 
    use_extended_stats=use_extended_stats@entry=true) at clausesel.c:875
#11 0x00000000007291b6 in clauselist_selectivity_ext (root=root@entry=0x2b5b530, clauses=0x2b88fc0, varRelid=7,
jointype=jointype@entry=JOIN_INNER,sjinfo=sjinfo@entry=0x0, use_extended_stats=use_extended_stats@entry=true)
 
    at clausesel.c:185
#12 0x000000000072962e in clauselist_selectivity (root=root@entry=0x2b5b530, clauses=<optimized out>,
varRelid=<optimizedout>, jointype=jointype@entry=JOIN_INNER, sjinfo=sjinfo@entry=0x0) at clausesel.c:108
 
#13 0x000000000072fb1d in get_parameterized_baserel_size (root=root@entry=0x2b5b530, rel=rel@entry=0x2b73900,
param_clauses=param_clauses@entry=0x2b88f68)at costsize.c:5015
 
#14 0x00000000007836f6 in get_baserel_parampathinfo (root=root@entry=0x2b5b530, baserel=baserel@entry=0x2b73900,
required_outer=required_outer@entry=0x2b86478)at relnode.c:1346
 
#15 0x0000000000776819 in create_seqscan_path (root=root@entry=0x2b5b530, rel=rel@entry=0x2b73900,
required_outer=required_outer@entry=0x2b86478,parallel_workers=parallel_workers@entry=0) at pathnode.c:937
 
#16 0x000000000077a32c in reparameterize_path (root=root@entry=0x2b5b530, path=path@entry=0x2b847b0,
required_outer=required_outer@entry=0x2b86478,loop_count=loop_count@entry=1) at pathnode.c:3872
 
#17 0x00000000007249bc in get_cheapest_parameterized_child_path (root=root@entry=0x2b5b530, rel=<optimized out>,
required_outer=required_outer@entry=0x2b86478)at allpaths.c:1996
 
#18 0x0000000000727619 in add_paths_to_append_rel (root=root@entry=0x2b5b530, rel=rel@entry=0x2b6a6a8,
live_childrels=live_childrels@entry=0x2b858e8)at allpaths.c:1597
 
#19 0x0000000000728084 in set_append_rel_pathlist (root=root@entry=0x2b5b530, rel=rel@entry=0x2b6a6a8, rti=rti@entry=6,
rte=rte@entry=0x2b5e1c0)at allpaths.c:1270
 
#20 0x0000000000727e17 in set_rel_pathlist (root=root@entry=0x2b5b530, rel=0x2b6a6a8, rti=rti@entry=6, rte=0x2b5e1c0)
atallpaths.c:483
 
#21 0x0000000000727f8a in set_base_rel_pathlists (root=root@entry=0x2b5b530) at allpaths.c:355
#22 0x00000000007286fd in make_one_rel (root=root@entry=0x2b5b530, joinlist=joinlist@entry=0x2b6fd98) at
allpaths.c:225
#23 0x00000000007512d5 in query_planner (root=root@entry=0x2b5b530, qp_callback=qp_callback@entry=0x75300a
<standard_qp_callback>,qp_extra=qp_extra@entry=0x7ffe5baa3670) at planmain.c:276
 
#24 0x00000000007589ec in grouping_planner (root=root@entry=0x2b5b530, tuple_fraction=<optimized out>,
tuple_fraction@entry=0)at planner.c:1467
 
#25 0x000000000075a5f2 in subquery_planner (glob=<optimized out>, parse=parse@entry=0x2b23c08,
parent_root=parent_root@entry=0x2736768,hasRecursion=hasRecursion@entry=false, tuple_fraction=<optimized out>) at
planner.c:1044
#26 0x0000000000726567 in set_subquery_pathlist (root=root@entry=0x2736768, rel=rel@entry=0x2755f30, rti=rti@entry=6,
rte=rte@entry=0x28c9980)at allpaths.c:2589
 
#27 0x000000000072681c in set_rel_size (root=root@entry=0x2736768, rel=rel@entry=0x2755f30, rti=rti@entry=6,
rte=rte@entry=0x28c9980)at allpaths.c:425
 
#28 0x0000000000726996 in set_base_rel_sizes (root=root@entry=0x2736768) at allpaths.c:326
#29 0x0000000000728663 in make_one_rel (root=root@entry=0x2736768, joinlist=joinlist@entry=0x274d038) at
allpaths.c:188
#30 0x00000000007512d5 in query_planner (root=root@entry=0x2736768, qp_callback=qp_callback@entry=0x75300a
<standard_qp_callback>,qp_extra=qp_extra@entry=0x7ffe5baa39d0) at planmain.c:276
 
#31 0x00000000007589ec in grouping_planner (root=root@entry=0x2736768, tuple_fraction=<optimized out>,
tuple_fraction@entry=0)at planner.c:1467
 
#32 0x000000000075a5f2 in subquery_planner (glob=glob@entry=0x2483430, parse=parse@entry=0x289c7c8,
parent_root=parent_root@entry=0x0,hasRecursion=hasRecursion@entry=false, tuple_fraction=tuple_fraction@entry=0)
 
    at planner.c:1044

I think this is what's needed.

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 14e0885f19f..4450f0d682f 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5240,6 +5240,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
             /* skip stats without per-expression stats */
             if (info->kind != STATS_EXT_EXPRESSIONS)
                 continue;
+            if (info->inherit != rte->inh)
+                continue;
 
             pos = 0;
             foreach(expr_item, info->exprs)




On Mon, Oct 31, 2022 at 1:05 AM Justin Pryzby <pryzby@telsasoft.com> wrote:
I think this is what's needed.

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 14e0885f19f..4450f0d682f 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5240,6 +5240,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
                        /* skip stats without per-expression stats */
                        if (info->kind != STATS_EXT_EXPRESSIONS)
                                continue;
+                       if (info->inherit != rte->inh)
+                               continue;

                        pos = 0;
                        foreach(expr_item, info->exprs)
 
I think we also need to do this when loading the ndistinct value, to
skip statistics with mismatching stxdinherit in
estimate_multivariate_ndistinct().

Thanks
Richard

On Mon, Oct 31, 2022 at 12:26 PM Richard Guo <guofenglinux@gmail.com> wrote:
On Mon, Oct 31, 2022 at 1:05 AM Justin Pryzby <pryzby@telsasoft.com> wrote:
I think this is what's needed.

diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 14e0885f19f..4450f0d682f 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5240,6 +5240,8 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
                        /* skip stats without per-expression stats */
                        if (info->kind != STATS_EXT_EXPRESSIONS)
                                continue;
+                       if (info->inherit != rte->inh)
+                               continue;

                        pos = 0;
                        foreach(expr_item, info->exprs)
 
I think we also need to do this when loading the ndistinct value, to
skip statistics with mismatching stxdinherit in
estimate_multivariate_ndistinct().
 
To be concrete, I mean something like attached.

BTW, I noticed a micro-optimization opportunity in examine_variable that
we can fetch the RangeTblEntry for 'onerel' outside the foreach loop
when iterating the extended stats so that we can do it only once rather
than for each stat.

Thanks
Richard
Attachment

Re: pg15 inherited stats expressions: cache lookup failed for statistics object

From
Michael Paquier
Date:
On Mon, Oct 31, 2022 at 01:12:09PM +0800, Richard Guo wrote:
> BTW, I noticed a micro-optimization opportunity in examine_variable that
> we can fetch the RangeTblEntry for 'onerel' outside the foreach loop
> when iterating the extended stats so that we can do it only once rather
> than for each stat.

Isn't that the kind of thing where we'd better have some regression
coverage?
--
Michael

Attachment

Re: pg15 inherited stats expressions: cache lookup failed for statistics object

From
Richard Guo
Date:

On Mon, Oct 31, 2022 at 1:33 PM Michael Paquier <michael@paquier.xyz> wrote:
On Mon, Oct 31, 2022 at 01:12:09PM +0800, Richard Guo wrote:
> BTW, I noticed a micro-optimization opportunity in examine_variable that
> we can fetch the RangeTblEntry for 'onerel' outside the foreach loop
> when iterating the extended stats so that we can do it only once rather
> than for each stat.

Isn't that the kind of thing where we'd better have some regression
coverage?
 
Yeah, we need to have some regression tests for that.  I come up with a
case in stats_ext like below

CREATE STATISTICS stxdinp ON (a + 1), a, b FROM stxdinp;
SELECT * FROM check_estimated_rows('SELECT a + 1, b FROM ONLY stxdinp GROUP BY 1, 2');

This case should be able to cover both expression stats and ndistinct
stats.  Hence, attach v2 patch.

Thanks
Richard
Attachment

Re: pg15 inherited stats expressions: cache lookup failed for statistics object

From
Justin Pryzby
Date:
On Tue, Nov 01, 2022 at 05:33:24PM +0800, Richard Guo wrote:
> On Mon, Oct 31, 2022 at 1:33 PM Michael Paquier <michael@paquier.xyz> wrote:
> 
> > On Mon, Oct 31, 2022 at 01:12:09PM +0800, Richard Guo wrote:
> > > BTW, I noticed a micro-optimization opportunity in examine_variable that
> > > we can fetch the RangeTblEntry for 'onerel' outside the foreach loop
> > > when iterating the extended stats so that we can do it only once rather
> > > than for each stat.
> >
> > Isn't that the kind of thing where we'd better have some regression
> > coverage?
> 
> Yeah, we need to have some regression tests for that.  I come up with a
> case in stats_ext like below

Well done

> This case should be able to cover both expression stats and ndistinct
> stats.  Hence, attach v2 patch.

Thanks for finishing it up.

I added a CF entry and marked RFC.
This should be included in v15.1.

-- 
Justin



Justin Pryzby <pryzby@telsasoft.com> writes:
> I added a CF entry and marked RFC.
> This should be included in v15.1.

Right, done.

            regards, tom lane



Re: pg15 inherited stats expressions: cache lookup failed for statistics object

From
Justin Pryzby
Date:
On Tue, Nov 01, 2022 at 02:35:43PM -0400, Tom Lane wrote:
> Justin Pryzby <pryzby@telsasoft.com> writes:
> > I added a CF entry and marked RFC.
> > This should be included in v15.1.
> 
> Right, done.

Thanks.  Yesterday, I realized that the bug was exposed here after we
accidentally recreated a table as relkind=r rather than relkind=p...

-- 
Justin