1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-05 02:22:28 +03:00

Fix some planner performance problems with large WHERE clauses, by

introducing new 'FastList' list-construction subroutines to use in
hot spots.  This avoids the O(N^2) behavior of repeated lappend's
by keeping a tail pointer, while not changing behavior by reversing
list order as the lcons() method would do.
This commit is contained in:
Tom Lane
2003-05-28 22:32:50 +00:00
parent 0f3c68aa43
commit 8a6ac83dab
8 changed files with 374 additions and 202 deletions

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.48 2003/02/09 06:56:27 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.49 2003/05/28 22:32:49 tgl Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
@@ -141,9 +141,9 @@ lconso(Oid datum, List *list)
* MORE EXPENSIVE THAN lcons
*/
List *
lappend(List *list, void *obj)
lappend(List *list, void *datum)
{
return nconc(list, makeList1(obj));
return nconc(list, makeList1(datum));
}
/*
@@ -195,6 +195,120 @@ nconc(List *l1, List *l2)
return l1; /* list1 is now list1+list2 */
}
/*
* FastAppend - append to a FastList.
*
* For long lists this is significantly faster than repeated lappend's,
* since we avoid having to chase down the list again each time.
*/
void
FastAppend(FastList *fl, void *datum)
{
List *cell = makeList1(datum);
if (fl->tail)
{
lnext(fl->tail) = cell;
fl->tail = cell;
}
else
{
/* First cell of list */
Assert(fl->head == NIL);
fl->head = fl->tail = cell;
}
}
/*
* FastAppendi - same for integers
*/
void
FastAppendi(FastList *fl, int datum)
{
List *cell = makeListi1(datum);
if (fl->tail)
{
lnext(fl->tail) = cell;
fl->tail = cell;
}
else
{
/* First cell of list */
Assert(fl->head == NIL);
fl->head = fl->tail = cell;
}
}
/*
* FastAppendo - same for Oids
*/
void
FastAppendo(FastList *fl, Oid datum)
{
List *cell = makeListo1(datum);
if (fl->tail)
{
lnext(fl->tail) = cell;
fl->tail = cell;
}
else
{
/* First cell of list */
Assert(fl->head == NIL);
fl->head = fl->tail = cell;
}
}
/*
* FastConc - nconc() for FastList building
*
* Note that the cells of the second argument are absorbed into the FastList.
*/
void
FastConc(FastList *fl, List *cells)
{
if (cells == NIL)
return; /* nothing to do */
if (fl->tail)
{
lnext(fl->tail) = cells;
}
else
{
/* First cell of list */
Assert(fl->head == NIL);
fl->head = cells;
}
while (lnext(cells) != NIL)
cells = lnext(cells);
fl->tail = cells;
}
/*
* FastConcFast - nconc() for FastList building
*
* Note that the cells of the second argument are absorbed into the first.
*/
void
FastConcFast(FastList *fl, FastList *fl2)
{
if (fl2->head == NIL)
return; /* nothing to do */
if (fl->tail)
{
lnext(fl->tail) = fl2->head;
}
else
{
/* First cell of list */
Assert(fl->head == NIL);
fl->head = fl2->head;
}
fl->tail = fl2->tail;
}
/*
* nth
*