Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500
От
Tom Lane
Тема
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500
Дата
Msg-id
1450797.1704580874@sss.pgh.pa.us
Ответ на
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 (Alexander Lakhin)
Список
Дерево обсуждения
Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Hans Buschmann <buschmann@nidsa.net>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tomas Vondra <tomas.vondra@enterprisedb.com>
AW: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Hans Buschmann <buschmann@nidsa.net>
Re: AW: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tomas Vondra <tomas.vondra@enterprisedb.com>
Re: AW: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tomas Vondra <tomas.vondra@enterprisedb.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Jian Guo <gjian@vmware.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tomas Vondra <tomas.vondra@enterprisedb.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Jian Guo <gjian@vmware.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Laurenz Albe <laurenz.albe@cybertec.at>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 "David G. Johnston" <david.g.johnston@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Alexander Lakhin <exclusion@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 vignesh C <vignesh21@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 vignesh C <vignesh21@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tom Lane <tgl@sss.pgh.pa.us>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Richard Guo <guofenglinux@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Tomas Vondra <tomas.vondra@enterprisedb.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Jian Guo <gjian@vmware.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 jian he <jian.universality@gmail.com>
Re: Wrong rows estimations with joins of CTEs slows queries by more than factor 500 Jian Guo <gjian@vmware.com>
Alexander Lakhin writes:
> Please look at the following query:
> CREATE TABLE t(i int);
> INSERT INTO t VALUES (1);
> VACUUM ANALYZE t;
> WITH ir AS (INSERT INTO t VALUES (2) RETURNING i)
> SELECT * FROM ir WHERE i = 2;
> which produces ERROR: no relation entry for relid 1
> starting from f7816aec2.
Thanks for the report! I guess we need something like the attached.
I'm surprised that this hasn't been noticed before; was the case
really unreachable before?
regards, tom lane
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 5a9ce44532..22d01cef5b 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -420,6 +420,19 @@ find_base_rel(PlannerInfo *root, int relid)
return NULL; /* keep compiler quiet */
}
+/*
+ * find_base_rel_noerr
+ * Find a base or otherrel relation entry, returning NULL if there's none
+ */
+RelOptInfo *
+find_base_rel_noerr(PlannerInfo *root, int relid)
+{
+ /* use an unsigned comparison to prevent negative array element access */
+ if ((uint32) relid < (uint32) root->simple_rel_array_size)
+ return root->simple_rel_array[relid];
+ return NULL;
+}
+
/*
* find_base_rel_ignore_join
* Find a base or otherrel relation entry, which must already exist.
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index dbcd98d985..cea777e9d4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -119,6 +119,7 @@
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "parser/parse_clause.h"
+#include "parser/parse_relation.h"
#include "parser/parsetree.h"
#include "statistics/statistics.h"
#include "storage/bufmgr.h"
@@ -5434,17 +5435,30 @@ examine_simple_variable(PlannerInfo *root, Var *var,
if (HeapTupleIsValid(vardata->statsTuple))
{
- RelOptInfo *onerel = find_base_rel(root, var->varno);
+ RelOptInfo *onerel = find_base_rel_noerr(root, var->varno);
Oid userid;
/*
* Check if user has permission to read this column. We require
* all rows to be accessible, so there must be no securityQuals
- * from security barrier views or RLS policies. Use
- * onerel->userid if it's set, in case we're accessing the table
- * via a view.
+ * from security barrier views or RLS policies.
+ *
+ * Normally the Var will have an associated RelOptInfo from which
+ * we can find out which userid to do the check as; but it might
+ * not if it's a RETURNING Var for an INSERT target relation. In
+ * that case use the RTEPermissionInfo associated with the RTE.
*/
- userid = OidIsValid(onerel->userid) ? onerel->userid : GetUserId();
+ if (onerel)
+ userid = onerel->userid;
+ else
+ {
+ RTEPermissionInfo *perminfo;
+
+ perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
+ userid = perminfo->checkAsUser;
+ }
+ if (!OidIsValid(userid))
+ userid = GetUserId();
vardata->acl_ok =
rte->securityQuals == NIL &&
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 03a0e46e70..c43d97b48a 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -307,6 +307,7 @@ extern void expand_planner_arrays(PlannerInfo *root, int add_size);
extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
RelOptInfo *parent);
extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
+extern RelOptInfo *find_base_rel_noerr(PlannerInfo *root, int relid);
extern RelOptInfo *find_base_rel_ignore_join(PlannerInfo *root, int relid);
extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids);
extern RelOptInfo *build_join_rel(PlannerInfo *root,
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index 69c56ce207..3cf969d938 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -654,6 +654,24 @@ select count(*) from tenk1 a
-> CTE Scan on x
(8 rows)
+explain (costs off)
+with x as materialized (insert into tenk1 default values returning unique1)
+select count(*) from tenk1 a
+ where unique1 in (select * from x);
+ QUERY PLAN
+------------------------------------------------------------
+ Aggregate
+ CTE x
+ -> Insert on tenk1
+ -> Result
+ -> Nested Loop
+ -> HashAggregate
+ Group Key: x.unique1
+ -> CTE Scan on x
+ -> Index Only Scan using tenk1_unique1 on tenk1 a
+ Index Cond: (unique1 = x.unique1)
+(10 rows)
+
-- SEARCH clause
create temp table graph0( f int, t int, label text );
insert into graph0 values
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index 3ef9898866..ff68e21e2e 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -354,6 +354,11 @@ with x as materialized (select unique1 from tenk1 b)
select count(*) from tenk1 a
where unique1 in (select * from x);
+explain (costs off)
+with x as materialized (insert into tenk1 default values returning unique1)
+select count(*) from tenk1 a
+ where unique1 in (select * from x);
+
-- SEARCH clause
create temp table graph0( f int, t int, label text );
В списке pgsql-hackers по дате отправления