Re: A question on the query planner - Mailing list pgsql-performance

From Tom Lane
Subject Re: A question on the query planner
Date
Msg-id 2704.1070473746@sss.pgh.pa.us
Whole thread Raw
In response to Re: A question on the query planner  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: A question on the query planner  (Jared Carr <jared@89glass.com>)
Re: A question on the query planner  (Gaetano Mendola <mendola@bigfoot.com>)
List pgsql-performance
> Hmmm ... [squints] ... it's not supposed to do that ...

The attached patch seems to make it better.

            regards, tom lane


Index: src/backend/optimizer/path/costsize.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/optimizer/path/costsize.c,v
retrieving revision 1.115
diff -c -r1.115 costsize.c
*** src/backend/optimizer/path/costsize.c    5 Oct 2003 22:44:25 -0000    1.115
--- src/backend/optimizer/path/costsize.c    3 Dec 2003 17:40:58 -0000
***************
*** 1322,1327 ****
--- 1322,1331 ----
      float4       *numbers;
      int            nnumbers;

+     /* Ignore any binary-compatible relabeling */
+     if (var && IsA(var, RelabelType))
+         var = (Var *) ((RelabelType *) var)->arg;
+
      /*
       * Lookup info about var's relation and attribute; if none available,
       * return default estimate.
Index: src/backend/optimizer/path/pathkeys.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/optimizer/path/pathkeys.c,v
retrieving revision 1.53
diff -c -r1.53 pathkeys.c
*** src/backend/optimizer/path/pathkeys.c    4 Aug 2003 02:40:00 -0000    1.53
--- src/backend/optimizer/path/pathkeys.c    3 Dec 2003 17:40:58 -0000
***************
*** 25,36 ****
  #include "optimizer/tlist.h"
  #include "optimizer/var.h"
  #include "parser/parsetree.h"
  #include "parser/parse_func.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"


! static PathKeyItem *makePathKeyItem(Node *key, Oid sortop);
  static List *make_canonical_pathkey(Query *root, PathKeyItem *item);
  static Var *find_indexkey_var(Query *root, RelOptInfo *rel,
                    AttrNumber varattno);
--- 25,37 ----
  #include "optimizer/tlist.h"
  #include "optimizer/var.h"
  #include "parser/parsetree.h"
+ #include "parser/parse_expr.h"
  #include "parser/parse_func.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"


! static PathKeyItem *makePathKeyItem(Node *key, Oid sortop, bool checkType);
  static List *make_canonical_pathkey(Query *root, PathKeyItem *item);
  static Var *find_indexkey_var(Query *root, RelOptInfo *rel,
                    AttrNumber varattno);
***************
*** 41,50 ****
   *        create a PathKeyItem node
   */
  static PathKeyItem *
! makePathKeyItem(Node *key, Oid sortop)
  {
      PathKeyItem *item = makeNode(PathKeyItem);

      item->key = key;
      item->sortop = sortop;
      return item;
--- 42,70 ----
   *        create a PathKeyItem node
   */
  static PathKeyItem *
! makePathKeyItem(Node *key, Oid sortop, bool checkType)
  {
      PathKeyItem *item = makeNode(PathKeyItem);

+     /*
+      * Some callers pass expressions that are not necessarily of the same
+      * type as the sort operator expects as input (for example when dealing
+      * with an index that uses binary-compatible operators).  We must relabel
+      * these with the correct type so that the key expressions will be seen
+      * as equal() to expressions that have been correctly labeled.
+      */
+     if (checkType)
+     {
+         Oid            lefttype,
+                     righttype;
+
+         op_input_types(sortop, &lefttype, &righttype);
+         if (exprType(key) != lefttype)
+             key = (Node *) makeRelabelType((Expr *) key,
+                                            lefttype, -1,
+                                            COERCE_DONTCARE);
+     }
+
      item->key = key;
      item->sortop = sortop;
      return item;
***************
*** 70,78 ****
  {
      Expr       *clause = restrictinfo->clause;
      PathKeyItem *item1 = makePathKeyItem(get_leftop(clause),
!                                          restrictinfo->left_sortop);
      PathKeyItem *item2 = makePathKeyItem(get_rightop(clause),
!                                          restrictinfo->right_sortop);
      List       *newset,
                 *cursetlink;

--- 90,100 ----
  {
      Expr       *clause = restrictinfo->clause;
      PathKeyItem *item1 = makePathKeyItem(get_leftop(clause),
!                                          restrictinfo->left_sortop,
!                                          false);
      PathKeyItem *item2 = makePathKeyItem(get_rightop(clause),
!                                          restrictinfo->right_sortop,
!                                          false);
      List       *newset,
                 *cursetlink;

***************
*** 668,674 ****
          }

          /* OK, make a sublist for this sort key */
!         item = makePathKeyItem(indexkey, sortop);
          cpathkey = make_canonical_pathkey(root, item);

          /*
--- 690,696 ----
          }

          /* OK, make a sublist for this sort key */
!         item = makePathKeyItem(indexkey, sortop, true);
          cpathkey = make_canonical_pathkey(root, item);

          /*
***************
*** 785,791 ****
                                          tle->resdom->restypmod,
                                          0);
                      outer_item = makePathKeyItem((Node *) outer_var,
!                                                  sub_item->sortop);
                      /* score = # of mergejoin peers */
                      score = count_canonical_peers(root, outer_item);
                      /* +1 if it matches the proper query_pathkeys item */
--- 807,814 ----
                                          tle->resdom->restypmod,
                                          0);
                      outer_item = makePathKeyItem((Node *) outer_var,
!                                                  sub_item->sortop,
!                                                  true);
                      /* score = # of mergejoin peers */
                      score = count_canonical_peers(root, outer_item);
                      /* +1 if it matches the proper query_pathkeys item */
***************
*** 893,899 ****
          PathKeyItem *pathkey;

          sortkey = get_sortgroupclause_expr(sortcl, tlist);
!         pathkey = makePathKeyItem(sortkey, sortcl->sortop);

          /*
           * The pathkey becomes a one-element sublist, for now;
--- 916,922 ----
          PathKeyItem *pathkey;

          sortkey = get_sortgroupclause_expr(sortcl, tlist);
!         pathkey = makePathKeyItem(sortkey, sortcl->sortop, true);

          /*
           * The pathkey becomes a one-element sublist, for now;
***************
*** 937,943 ****
      {
          oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
          key = get_leftop(restrictinfo->clause);
!         item = makePathKeyItem(key, restrictinfo->left_sortop);
          restrictinfo->left_pathkey = make_canonical_pathkey(root, item);
          MemoryContextSwitchTo(oldcontext);
      }
--- 960,966 ----
      {
          oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
          key = get_leftop(restrictinfo->clause);
!         item = makePathKeyItem(key, restrictinfo->left_sortop, false);
          restrictinfo->left_pathkey = make_canonical_pathkey(root, item);
          MemoryContextSwitchTo(oldcontext);
      }
***************
*** 945,951 ****
      {
          oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
          key = get_rightop(restrictinfo->clause);
!         item = makePathKeyItem(key, restrictinfo->right_sortop);
          restrictinfo->right_pathkey = make_canonical_pathkey(root, item);
          MemoryContextSwitchTo(oldcontext);
      }
--- 968,974 ----
      {
          oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
          key = get_rightop(restrictinfo->clause);
!         item = makePathKeyItem(key, restrictinfo->right_sortop, false);
          restrictinfo->right_pathkey = make_canonical_pathkey(root, item);
          MemoryContextSwitchTo(oldcontext);
      }
Index: src/backend/utils/cache/lsyscache.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/cache/lsyscache.c,v
retrieving revision 1.108
diff -c -r1.108 lsyscache.c
*** src/backend/utils/cache/lsyscache.c    4 Oct 2003 18:22:59 -0000    1.108
--- src/backend/utils/cache/lsyscache.c    3 Dec 2003 17:40:58 -0000
***************
*** 465,470 ****
--- 465,493 ----
  }

  /*
+  * op_input_types
+  *
+  *        Returns the left and right input datatypes for an operator
+  *        (InvalidOid if not relevant).
+  */
+ void
+ op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
+ {
+     HeapTuple    tp;
+     Form_pg_operator optup;
+
+     tp = SearchSysCache(OPEROID,
+                         ObjectIdGetDatum(opno),
+                         0, 0, 0);
+     if (!HeapTupleIsValid(tp))    /* shouldn't happen */
+         elog(ERROR, "cache lookup failed for operator %u", opno);
+     optup = (Form_pg_operator) GETSTRUCT(tp);
+     *lefttype = optup->oprleft;
+     *righttype = optup->oprright;
+     ReleaseSysCache(tp);
+ }
+
+ /*
   * op_mergejoinable
   *
   *        Returns the left and right sort operators corresponding to a
Index: src/include/utils/lsyscache.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/lsyscache.h,v
retrieving revision 1.82
diff -c -r1.82 lsyscache.h
*** src/include/utils/lsyscache.h    4 Oct 2003 18:22:59 -0000    1.82
--- src/include/utils/lsyscache.h    3 Dec 2003 17:41:00 -0000
***************
*** 40,45 ****
--- 40,46 ----
  extern bool opclass_is_hash(Oid opclass);
  extern RegProcedure get_opcode(Oid opno);
  extern char *get_opname(Oid opno);
+ extern void op_input_types(Oid opno, Oid *lefttype, Oid *righttype);
  extern bool op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp);
  extern void op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
                        RegProcedure *ltproc, RegProcedure *gtproc);

pgsql-performance by date:

Previous
From: Christopher Browne
Date:
Subject: Re: Minimum hardware requirements for Postgresql db
Next
From: Jared Carr
Date:
Subject: Re: A question on the query planner