mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Major optimizer improvement for joining a large number of tables.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.63 1999/02/08 04:29:03 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.64 1999/02/09 03:51:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1093,25 +1093,26 @@ CopyPathFields(Path *from, Path *newnode)
|
||||
|
||||
newnode->path_cost = from->path_cost;
|
||||
|
||||
newnode->path_order.ordtype = from->path_order.ordtype;
|
||||
if (from->path_order.ordtype == SORTOP_ORDER)
|
||||
newnode->path_order = makeNode(PathOrder);
|
||||
newnode->path_order->ordtype = from->path_order->ordtype;
|
||||
if (from->path_order->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
int len,
|
||||
i;
|
||||
Oid *ordering = from->path_order.ord.sortop;
|
||||
Oid *ordering = from->path_order->ord.sortop;
|
||||
|
||||
if (ordering)
|
||||
{
|
||||
for (len = 0; ordering[len] != 0; len++)
|
||||
;
|
||||
newnode->path_order.ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1));
|
||||
newnode->path_order->ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1));
|
||||
for (i = 0; i < len; i++)
|
||||
newnode->path_order.ord.sortop[i] = ordering[i];
|
||||
newnode->path_order.ord.sortop[len] = 0;
|
||||
newnode->path_order->ord.sortop[i] = ordering[i];
|
||||
newnode->path_order->ord.sortop[len] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
Node_Copy(from, newnode, path_order.ord.merge);
|
||||
Node_Copy(from, newnode, path_order->ord.merge);
|
||||
|
||||
Node_Copy(from, newnode, keys);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.26 1999/02/08 04:29:04 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.27 1999/02/09 03:51:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -337,33 +337,33 @@ _equalPath(Path *a, Path *b)
|
||||
/*
|
||||
* if (a->path_cost != b->path_cost) return(false);
|
||||
*/
|
||||
if (a->path_order.ordtype == SORTOP_ORDER)
|
||||
if (a->path_order->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (a->path_order.ord.sortop == NULL ||
|
||||
b->path_order.ord.sortop == NULL)
|
||||
if (a->path_order->ord.sortop == NULL ||
|
||||
b->path_order->ord.sortop == NULL)
|
||||
{
|
||||
if (a->path_order.ord.sortop != b->path_order.ord.sortop)
|
||||
if (a->path_order->ord.sortop != b->path_order->ord.sortop)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (a->path_order.ord.sortop[i] != 0 &&
|
||||
b->path_order.ord.sortop[i] != 0)
|
||||
while (a->path_order->ord.sortop[i] != 0 &&
|
||||
b->path_order->ord.sortop[i] != 0)
|
||||
{
|
||||
if (a->path_order.ord.sortop[i] != b->path_order.ord.sortop[i])
|
||||
if (a->path_order->ord.sortop[i] != b->path_order->ord.sortop[i])
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
if (a->path_order.ord.sortop[i] != 0 ||
|
||||
b->path_order.ord.sortop[i] != 0)
|
||||
if (a->path_order->ord.sortop[i] != 0 ||
|
||||
b->path_order->ord.sortop[i] != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!equal(a->path_order.ord.merge, b->path_order.ord.merge))
|
||||
if (!equal(a->path_order->ord.merge, b->path_order->ord.merge))
|
||||
return false;
|
||||
}
|
||||
if (!equal(a->keys, b->keys))
|
||||
@@ -433,9 +433,9 @@ _equalHashPath(HashPath *a, HashPath *b)
|
||||
return false;
|
||||
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
|
||||
return false;
|
||||
if (!equal((a->outerhashkeys), (b->outerhashkeys)))
|
||||
if (!equal(a->outerhashkeys, b->outerhashkeys))
|
||||
return false;
|
||||
if (!equal((a->innerhashkeys), (b->innerhashkeys)))
|
||||
if (!equal(a->innerhashkeys, b->innerhashkeys))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.2 1999/02/08 04:29:04 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.3 1999/02/09 03:51:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -756,13 +756,16 @@ _freeRelOptInfo(RelOptInfo * node)
|
||||
static void
|
||||
FreePathFields(Path *node)
|
||||
{
|
||||
if (node->path_order.ordtype == SORTOP_ORDER)
|
||||
if (node->path_order->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
if (node->path_order.ord.sortop)
|
||||
pfree(node->path_order.ord.sortop);
|
||||
if (node->path_order->ord.sortop)
|
||||
pfree(node->path_order->ord.sortop);
|
||||
}
|
||||
else
|
||||
freeObject(node->path_order.ord.merge);
|
||||
freeObject(node->path_order->ord.merge);
|
||||
|
||||
pfree(node->path_order); /* is it an object, but we don't have
|
||||
separate free for it */
|
||||
|
||||
freeObject(node->keys);
|
||||
|
||||
@@ -1171,7 +1174,6 @@ freeObject(void *node)
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
|
||||
/*
|
||||
* PLAN NODES
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.15 1998/09/01 04:29:05 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.16 1999/02/09 03:51:13 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* XXX a few of the following functions are duplicated to handle
|
||||
@@ -368,8 +368,8 @@ member(void *l1, List *l2)
|
||||
List *i;
|
||||
|
||||
foreach(i, l2)
|
||||
if (equal((Node *) (lfirst(i)), (Node *) l1))
|
||||
return true;
|
||||
if (equal((Node *) l1, (Node *) lfirst(i)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: outfuncs.c,v 1.65 1999/02/05 19:59:25 momjian Exp $
|
||||
* $Id: outfuncs.c,v 1.66 1999/02/09 03:51:13 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@@ -855,7 +855,7 @@ _outEState(StringInfo str, EState *node)
|
||||
* Stuff from relation.h
|
||||
*/
|
||||
static void
|
||||
_outRelOptInfo(StringInfo str, RelOptInfo * node)
|
||||
_outRelOptInfo(StringInfo str, RelOptInfo *node)
|
||||
{
|
||||
appendStringInfo(str, " RELOPTINFO :relids ");
|
||||
_outIntList(str, node->relids);
|
||||
@@ -924,6 +924,35 @@ _outRowMark(StringInfo str, RowMark *node)
|
||||
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Path is a subclass of Node.
|
||||
*/
|
||||
static void
|
||||
_outPathOrder(StringInfo str, PathOrder *node)
|
||||
{
|
||||
appendStringInfo(str, " PATHORDER :ordtype %d ",
|
||||
node->ordtype);
|
||||
if (node->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
int i;
|
||||
|
||||
appendStringInfo(str, " :sortop ");
|
||||
if (node->ord.sortop == NULL)
|
||||
appendStringInfo(str, "<>");
|
||||
else
|
||||
{
|
||||
for (i=0; node->ord.sortop[i] != 0; i++)
|
||||
appendStringInfo(str, " %d ", node->ord.sortop[i]);
|
||||
appendStringInfo(str, " %d ", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
appendStringInfo(str, " :merge ");
|
||||
_outNode(str,node->ord.merge);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Path is a subclass of Node.
|
||||
*/
|
||||
@@ -934,6 +963,9 @@ _outPath(StringInfo str, Path *node)
|
||||
node->pathtype,
|
||||
node->path_cost);
|
||||
_outNode(str, node->keys);
|
||||
|
||||
appendStringInfo(str, " :path_order ");
|
||||
_outNode(str, node->path_order);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -948,6 +980,9 @@ _outIndexPath(StringInfo str, IndexPath *node)
|
||||
node->path.path_cost);
|
||||
_outNode(str, node->path.keys);
|
||||
|
||||
appendStringInfo(str, " :path_order ");
|
||||
_outNode(str, node->path.path_order);
|
||||
|
||||
appendStringInfo(str, " :indexid ");
|
||||
_outIntList(str, node->indexid);
|
||||
|
||||
@@ -967,6 +1002,9 @@ _outJoinPath(StringInfo str, JoinPath *node)
|
||||
node->path.path_cost);
|
||||
_outNode(str, node->path.keys);
|
||||
|
||||
appendStringInfo(str, " :path_order ");
|
||||
_outNode(str, node->path.path_order);
|
||||
|
||||
appendStringInfo(str, " :pathinfo ");
|
||||
_outNode(str, node->pathinfo);
|
||||
|
||||
@@ -995,6 +1033,9 @@ _outMergePath(StringInfo str, MergePath *node)
|
||||
node->jpath.path.path_cost);
|
||||
_outNode(str, node->jpath.path.keys);
|
||||
|
||||
appendStringInfo(str, " :path_order ");
|
||||
_outNode(str, node->jpath.path.path_order);
|
||||
|
||||
appendStringInfo(str, " :pathinfo ");
|
||||
_outNode(str, node->jpath.pathinfo);
|
||||
|
||||
@@ -1032,6 +1073,9 @@ _outHashPath(StringInfo str, HashPath *node)
|
||||
node->jpath.path.path_cost);
|
||||
_outNode(str, node->jpath.path.keys);
|
||||
|
||||
appendStringInfo(str, " :path_order ");
|
||||
_outNode(str, node->jpath.path.path_order);
|
||||
|
||||
appendStringInfo(str, " :pathinfo ");
|
||||
_outNode(str, node->jpath.pathinfo);
|
||||
|
||||
@@ -1548,6 +1592,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_RowMark:
|
||||
_outRowMark(str, obj);
|
||||
break;
|
||||
case T_PathOrder:
|
||||
_outPathOrder(str, obj);
|
||||
break;
|
||||
case T_Path:
|
||||
_outPath(str, obj);
|
||||
break;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.50 1999/02/08 04:29:04 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.51 1999/02/09 03:51:13 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "catalog/pg_index.h"
|
||||
#include "catalog/pg_type.h"
|
||||
|
||||
#include "nodes/primnodes.h"
|
||||
@@ -1450,6 +1451,54 @@ _readRowMark()
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readPathOrder
|
||||
*
|
||||
* PathOrder is part of Path and it's subclasses.
|
||||
* ----------------
|
||||
*/
|
||||
static PathOrder *
|
||||
_readPathOrder()
|
||||
{
|
||||
PathOrder *local_node;
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
local_node = makeNode(PathOrder);
|
||||
|
||||
token = lsptok(NULL, &length); /* get :ordtype */
|
||||
token = lsptok(NULL, &length); /* now read it */
|
||||
local_node->ordtype = atol(token);
|
||||
|
||||
if (local_node->ordtype == SORTOP_ORDER)
|
||||
{
|
||||
token = lsptok(NULL, &length); /* get :sortop */
|
||||
|
||||
if (length == 0)
|
||||
local_node->ord.sortop = NULL;
|
||||
else
|
||||
{
|
||||
int i = -1;
|
||||
|
||||
local_node->ord.sortop = palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1));
|
||||
|
||||
do {
|
||||
i++;
|
||||
Assert(i <= INDEX_MAX_KEYS);
|
||||
token = lsptok(NULL, &length); /* now read it */
|
||||
local_node->ord.sortop[i] = strtoul(token, NULL, 10);
|
||||
} while (local_node->ord.sortop[i] != 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token = lsptok(NULL, &length); /* get :merge */
|
||||
local_node->ord.merge = nodeRead(true); /* now read it */
|
||||
}
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readPath
|
||||
*
|
||||
@@ -1473,10 +1522,8 @@ _readPath()
|
||||
token = lsptok(NULL, &length); /* now read it */
|
||||
local_node->path_cost = (Cost) atof(token);
|
||||
|
||||
#if 0
|
||||
token = lsptok(NULL, &length); /* get :path_order */
|
||||
local_node->path_order = nodeRead(true); /* now read it */
|
||||
#endif
|
||||
local_node->path_order = nodeRead(true); /* now read it */
|
||||
|
||||
token = lsptok(NULL, &length); /* get :keys */
|
||||
local_node->keys = nodeRead(true); /* now read it */
|
||||
@@ -1507,10 +1554,8 @@ _readIndexPath()
|
||||
token = lsptok(NULL, &length); /* now read it */
|
||||
local_node->path.path_cost = (Cost) atof(token);
|
||||
|
||||
#if 0
|
||||
token = lsptok(NULL, &length); /* get :path_order */
|
||||
local_node->path.path_order = nodeRead(true); /* now read it */
|
||||
#endif
|
||||
local_node->path.path_order = nodeRead(true); /* now read it */
|
||||
|
||||
token = lsptok(NULL, &length); /* get :keys */
|
||||
local_node->path.keys = nodeRead(true); /* now read it */
|
||||
@@ -1548,10 +1593,8 @@ _readJoinPath()
|
||||
token = lsptok(NULL, &length); /* now read it */
|
||||
local_node->path.path_cost = (Cost) atof(token);
|
||||
|
||||
#if 0
|
||||
token = lsptok(NULL, &length); /* get :path_order */
|
||||
local_node->path.path_order = nodeRead(true); /* now read it */
|
||||
#endif
|
||||
|
||||
token = lsptok(NULL, &length); /* get :keys */
|
||||
local_node->path.keys = nodeRead(true); /* now read it */
|
||||
@@ -1615,10 +1658,8 @@ _readMergePath()
|
||||
|
||||
local_node->jpath.path.path_cost = (Cost) atof(token);
|
||||
|
||||
#if 0
|
||||
token = lsptok(NULL, &length); /* get :path_order */
|
||||
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
||||
#endif
|
||||
|
||||
token = lsptok(NULL, &length); /* get :keys */
|
||||
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
||||
@@ -1691,10 +1732,8 @@ _readHashPath()
|
||||
|
||||
local_node->jpath.path.path_cost = (Cost) atof(token);
|
||||
|
||||
#if 0
|
||||
token = lsptok(NULL, &length); /* get :path_order */
|
||||
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
||||
#endif
|
||||
|
||||
token = lsptok(NULL, &length); /* get :keys */
|
||||
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
||||
@@ -2071,6 +2110,8 @@ parsePlanString(void)
|
||||
return_value = _readTargetEntry();
|
||||
else if (!strncmp(token, "RTE", length))
|
||||
return_value = _readRangeTblEntry();
|
||||
else if (!strncmp(token, "PATHORDER", length))
|
||||
return_value = _readPathOrder();
|
||||
else if (!strncmp(token, "PATH", length))
|
||||
return_value = _readPath();
|
||||
else if (!strncmp(token, "INDEXPATH", length))
|
||||
|
||||
Reference in New Issue
Block a user