From 770671062f130a830aa89100c9aa2d26f8d4bf32 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 2 Nov 2016 15:50:15 -0400 Subject: [PATCH] Don't make FK-based selectivity estimates in inheritance situations. The foreign-key-aware logic for estimation of join sizes (added in commit 100340e2d) blindly tried to apply the concept to rels that are actually parents of inheritance trees. This is just plain wrong so far as the referenced relation is concerned, since the inheritance scan may well produce lots of rows that are not participating in the constraint. It's wrong for the referencing relation too, for the same reason; although on that end we could conceivably detect whether all members of the inheritance tree have equivalent FK constraints pointing to the same referenced rel, and then proceed more or less as we do now. But pending somebody writing code to do that, we must disable this, because it's producing completely silly estimates when there's an FK linking the heads of inheritance trees. Per bug #14404 from Clinton Adams. Back-patch to 9.6 where the new estimation logic came in. Report: <20161028200412.15987.96482@wrigleys.postgresql.org> --- src/backend/optimizer/util/plancat.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 5d18206b91..ad07baa60c 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -53,7 +53,7 @@ get_relation_info_hook_type get_relation_info_hook = NULL; static void get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel, - Relation relation); + Relation relation, bool inhparent); static bool infer_collation_opclass_match(InferenceElem *elem, Relation idxRel, List *idxExprs); static int32 get_rel_data_width(Relation rel, int32 *attr_widths); @@ -408,7 +408,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, } /* Collect info about relation's foreign keys, if relevant */ - get_relation_foreign_keys(root, rel, relation); + get_relation_foreign_keys(root, rel, relation, inhparent); heap_close(relation, NoLock); @@ -433,7 +433,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, */ static void get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel, - Relation relation) + Relation relation, bool inhparent) { List *rtable = root->parse->rtable; List *cachedfkeys; @@ -448,6 +448,15 @@ get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel, list_length(rtable) < 2) return; + /* + * If it's the parent of an inheritance tree, ignore its FKs. We could + * make useful FK-based deductions if we found that all members of the + * inheritance tree have equivalent FK constraints, but detecting that + * would require code that hasn't been written. + */ + if (inhparent) + return; + /* * Extract data about relation's FKs from the relcache. Note that this * list belongs to the relcache and might disappear in a cache flush, so @@ -488,6 +497,9 @@ get_relation_foreign_keys(PlannerInfo *root, RelOptInfo *rel, if (rte->rtekind != RTE_RELATION || rte->relid != cachedfk->confrelid) continue; + /* Ignore if it's an inheritance parent; doesn't really match */ + if (rte->inh) + continue; /* Ignore self-referential FKs; we only care about joins */ if (rti == rel->relid) continue;