Commit f5f366e1 authored by Bruce Momjian's avatar Bruce Momjian

Allow internal sorts to be stored in memory rather than in files.

parent 3bea7b13
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.5 1996/11/10 02:59:54 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.6 1997/08/06 03:41:29 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -374,6 +374,18 @@ ExecMergeTupleDump(ExprContext *econtext, MergeJoinState *mergestate)
printf("******** \n");
}
static void
CleanUpSort(Plan *plan) {
if (plan == NULL)
return;
if (plan->type == T_Sort) {
Sort *sort = (Sort *)plan;
psort_end(sort);
}
}
/* ----------------------------------------------------------------
* ExecMergeJoin
*
......@@ -676,6 +688,8 @@ ExecMergeJoin(MergeJoin *node)
*/
if (TupIsNull(outerTupleSlot)) {
MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
CleanUpSort(node->join.lefttree->lefttree);
CleanUpSort(node->join.righttree->lefttree);
return NULL;
}
......
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.36 1997/07/29 16:14:40 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.37 1997/08/06 03:41:41 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
......@@ -108,6 +108,7 @@ extern int lockingOff;
extern int NBuffers;
int fsyncOff = 0;
int SortMem = 512;
int dontExecute = 0;
static int ShowStats;
......@@ -1039,6 +1040,15 @@ PostgresMain(int argc, char *argv[])
flagQ = 1;
break;
case 'S':
/* ----------------
* S - amount of sort memory to use in 1k bytes
* ----------------
*/
SortMem = atoi(optarg);
break;
#ifdef NOT_USED
case 'S':
/* ----------------
* S - assume stable main memory
......@@ -1048,6 +1058,7 @@ PostgresMain(int argc, char *argv[])
flagS = 1;
SetTransactionFlushEnabled(false);
break;
#endif
case 's':
/* ----------------
......@@ -1173,6 +1184,7 @@ PostgresMain(int argc, char *argv[])
printf("\ttimings = %c\n", ShowStats ? 't' : 'f');
printf("\tdates = %s\n", EuroDates ? "European" : "Normal");
printf("\tbufsize = %d\n", NBuffers);
printf("\tsortmem = %d\n", SortMem);
printf("\tquery echo = %c\n", EchoQuery ? 't' : 'f');
printf("\tmultiplexed backend? = %c\n", multiplexedBackend ? 't' : 'f');
......@@ -1280,7 +1292,7 @@ PostgresMain(int argc, char *argv[])
*/
if (IsUnderPostmaster == false) {
puts("\nPOSTGRES backend interactive interface");
puts("$Revision: 1.36 $ $Date: 1997/07/29 16:14:40 $");
puts("$Revision: 1.37 $ $Date: 1997/08/06 03:41:41 $");
}
/* ----------------
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.3 1997/05/20 11:35:48 vadim Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/sort/Attic/lselect.c,v 1.4 1997/08/06 03:41:47 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -26,37 +26,14 @@
#include "utils/psort.h"
#include "utils/lselect.h"
extern Relation SortRdesc; /* later static */
/*
* PUTTUP - writes the next tuple
* ENDRUN - mark end of run
* GETLEN - reads the length of the next tuple
* ALLOCTUP - returns space for the new tuple
* SETTUPLEN - stores the length into the tuple
* GETTUP - reads the tuple
*
* Note:
* LEN field must be a short; FP is a stream
*/
#define PUTTUP(TUP, FP) fwrite((char *)TUP, (TUP)->t_len, 1, FP)
#define ENDRUN(FP) fwrite((char *)&shortzero, sizeof (shortzero), 1, FP)
#define GETLEN(LEN, FP) fread(&(LEN), sizeof (shortzero), 1, FP)
#define ALLOCTUP(LEN) ((HeapTuple)palloc((unsigned)LEN))
#define GETTUP(TUP, LEN, FP)\
fread((char *)(TUP) + sizeof (shortzero), 1, (LEN) - sizeof (shortzero), FP)
#define SETTUPLEN(TUP, LEN) (TUP)->t_len = LEN
/*
* USEMEM - record use of memory
* FREEMEM - record freeing of memory
* FULLMEM - 1 iff a tuple will fit
*/
#define USEMEM(AMT) SortMemory -= (AMT)
#define FREEMEM(AMT) SortMemory += (AMT)
#define LACKMEM() (SortMemory <= BLCKSZ) /* not accurate */
#define USEMEM(context,AMT) context->sortMem -= (AMT)
#define FREEMEM(context,AMT) context->sortMem += (AMT)
/*
* lmerge - merges two leftist trees into one
......@@ -67,12 +44,12 @@ extern Relation SortRdesc; /* later static */
* speed up code significantly.
*/
struct leftist *
lmerge(struct leftist *pt, struct leftist *qt)
lmerge(struct leftist *pt, struct leftist *qt, LeftistContext context)
{
register struct leftist *root, *majorLeftist, *minorLeftist;
int dist;
if (tuplecmp(pt->lt_tuple, qt->lt_tuple)) {
if (tuplecmp(pt->lt_tuple, qt->lt_tuple, context)) {
root = pt;
majorLeftist = qt;
} else {
......@@ -83,7 +60,7 @@ lmerge(struct leftist *pt, struct leftist *qt)
root->lt_left = majorLeftist;
else {
if ((minorLeftist = root->lt_right) != NULL)
majorLeftist = lmerge(majorLeftist, minorLeftist);
majorLeftist = lmerge(majorLeftist, minorLeftist, context);
if ((dist = root->lt_left->lt_dist) < majorLeftist->lt_dist) {
root->lt_dist = 1 + dist;
root->lt_right = root->lt_left;
......@@ -97,11 +74,11 @@ lmerge(struct leftist *pt, struct leftist *qt)
}
static struct leftist *
linsert(struct leftist *root, struct leftist *new1)
linsert(struct leftist *root, struct leftist *new1, LeftistContext context)
{
register struct leftist *left, *right;
if (! tuplecmp(root->lt_tuple, new1->lt_tuple)) {
if (! tuplecmp(root->lt_tuple, new1->lt_tuple, context)) {
new1->lt_left = root;
return(new1);
}
......@@ -116,7 +93,7 @@ linsert(struct leftist *root, struct leftist *new1)
}
return(root);
}
right = linsert(right, new1);
right = linsert(right, new1, context);
if (right->lt_dist < left->lt_dist) {
root->lt_dist = 1 + left->lt_dist;
root->lt_left = right;
......@@ -142,7 +119,8 @@ linsert(struct leftist *root, struct leftist *new1)
*/
HeapTuple
gettuple(struct leftist **treep,
short *devnum) /* device from which tuple came */
short *devnum, /* device from which tuple came */
LeftistContext context)
{
register struct leftist *tp;
HeapTuple tup;
......@@ -153,9 +131,9 @@ gettuple(struct leftist **treep,
if (tp->lt_dist == 1) /* lt_left == NULL */
*treep = tp->lt_left;
else
*treep = lmerge(tp->lt_left, tp->lt_right);
*treep = lmerge(tp->lt_left, tp->lt_right, context);
FREEMEM(sizeof (struct leftist));
FREEMEM(context,sizeof (struct leftist));
FREE(tp);
return(tup);
}
......@@ -169,14 +147,17 @@ gettuple(struct leftist **treep,
* Note:
* Currently never returns NULL BUG
*/
int
puttuple(struct leftist **treep, HeapTuple newtuple, int devnum)
void
puttuple(struct leftist **treep,
HeapTuple newtuple,
short devnum,
LeftistContext context)
{
register struct leftist *new1;
register struct leftist *tp;
new1 = (struct leftist *) palloc((unsigned) sizeof (struct leftist));
USEMEM(sizeof (struct leftist));
USEMEM(context,sizeof (struct leftist));
new1->lt_dist = 1;
new1->lt_devnum = devnum;
new1->lt_tuple = newtuple;
......@@ -185,38 +166,11 @@ puttuple(struct leftist **treep, HeapTuple newtuple, int devnum)
if ((tp = *treep) == NULL)
*treep = new1;
else
*treep = linsert(tp, new1);
return(1);
*treep = linsert(tp, new1, context);
return;
}
/*
* dumptuples - stores all the tuples in tree into file
*/
void
dumptuples(FILE *file)
{
register struct leftist *tp;
register struct leftist *newp;
HeapTuple tup;
tp = Tuples;
while (tp != NULL) {
tup = tp->lt_tuple;
if (tp->lt_dist == 1) /* lt_right == NULL */
newp = tp->lt_left;
else
newp = lmerge(tp->lt_left, tp->lt_right);
FREEMEM(sizeof (struct leftist));
FREE(tp);
PUTTUP(tup, file);
FREEMEM(tup->t_len);
FREE(tup);
tp = newp;
}
Tuples = NULL;
}
/*
* tuplecmp - Compares two tuples with respect CmpList
*
......@@ -225,7 +179,7 @@ dumptuples(FILE *file)
* Assumtions:
*/
int
tuplecmp(HeapTuple ltup, HeapTuple rtup)
tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context)
{
register char *lattr, *rattr;
int nkey = 0;
......@@ -238,24 +192,27 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
return(0);
if (rtup == (HeapTuple)NULL)
return(1);
while (nkey < Nkeys && !result) {
while (nkey < context->nKeys && !result) {
lattr = heap_getattr(ltup, InvalidBuffer,
Key[nkey].sk_attno,
RelationGetTupleDescriptor(SortRdesc),
&isnull);
context->scanKeys[nkey].sk_attno,
context->tupDesc, &isnull);
if (isnull)
return(0);
rattr = heap_getattr(rtup, InvalidBuffer,
Key[nkey].sk_attno,
RelationGetTupleDescriptor(SortRdesc),
context->scanKeys[nkey].sk_attno,
context->tupDesc,
&isnull);
if (isnull)
return(1);
if (Key[nkey].sk_flags & SK_COMMUTE) {
if (!(result = (long) (*Key[nkey].sk_func) (rattr, lattr)))
result = -(long) (*Key[nkey].sk_func) (lattr, rattr);
} else if (!(result = (long) (*Key[nkey].sk_func) (lattr, rattr)))
result = -(long) (*Key[nkey].sk_func) (rattr, lattr);
if (context->scanKeys[nkey].sk_flags & SK_COMMUTE) {
if (!(result =
(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr)))
result =
-(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr);
} else if (!(result =
(long) (*context->scanKeys[nkey].sk_func) (lattr, rattr)))
result =
-(long) (*context->scanKeys[nkey].sk_func) (rattr, lattr);
nkey++;
}
return (result == 1);
......@@ -263,7 +220,7 @@ tuplecmp(HeapTuple ltup, HeapTuple rtup)
#ifdef EBUG
void
checktree(struct leftist *tree)
checktree(struct leftist *tree, LeftistContext context)
{
int lnodes;
int rnodes;
......@@ -272,8 +229,8 @@ checktree(struct leftist *tree)
puts("Null tree.");
return;
}
lnodes = checktreer(tree->lt_left, 1);
rnodes = checktreer(tree->lt_right, 1);
lnodes = checktreer(tree->lt_left, 1, context);
rnodes = checktreer(tree->lt_right, 1, context);
if (lnodes < 0) {
lnodes = -lnodes;
puts("0:\tBad left side.");
......@@ -297,24 +254,24 @@ checktree(struct leftist *tree)
} else if (tree->lt_dist != 1+ tree->lt_right->lt_dist)
puts("0:\tDistance incorrect.");
if (lnodes > 0)
if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple))
if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context))
printf("%d:\tLeft child < parent.\n");
if (rnodes > 0)
if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple))
if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context))
printf("%d:\tRight child < parent.\n");
printf("Tree has %d nodes\n", 1 + lnodes + rnodes);
}
int
checktreer(struct leftist *tree, int level)
checktreer(struct leftist *tree, int level, LeftistContext context)
{
int lnodes, rnodes;
int error = 0;
if (tree == NULL)
return(0);
lnodes = checktreer(tree->lt_left, level + 1);
rnodes = checktreer(tree->lt_right, level + 1);
lnodes = checktreer(tree->lt_left, level + 1, context);
rnodes = checktreer(tree->lt_right, level + 1, context);
if (lnodes < 0) {
error = 1;
lnodes = -lnodes;
......@@ -349,12 +306,12 @@ checktreer(struct leftist *tree, int level)
printf("%d:\tDistance incorrect.\n", level);
}
if (lnodes > 0)
if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple)) {
if (tuplecmp(tree->lt_left->lt_tuple, tree->lt_tuple, context)) {
error = 1;
printf("%d:\tLeft child < parent.\n");
}
if (rnodes > 0)
if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple)) {
if (tuplecmp(tree->lt_right->lt_tuple, tree->lt_tuple, context)) {
error = 1;
printf("%d:\tRight child < parent.\n");
}
......
This diff is collapsed.
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: execnodes.h,v 1.6 1996/11/04 08:52:54 scrappy Exp $
* $Id: execnodes.h,v 1.7 1997/08/06 03:42:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -605,7 +605,7 @@ typedef struct SortState {
CommonScanState csstate; /* its first field is NodeTag */
bool sort_Flag;
ScanKey sort_Keys;
Relation sort_TempRelation;
bool cleaned;
} SortState;
/* ----------------
......
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: plannodes.h,v 1.5 1996/11/05 08:18:44 scrappy Exp $
* $Id: plannodes.h,v 1.6 1997/08/06 03:42:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -265,6 +265,8 @@ typedef struct Sort {
Oid tempid;
int keycount;
SortState *sortstate;
void *psortstate;
bool cleaned;
} Sort;
/* ----------------
......
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: lselect.h,v 1.3 1996/11/04 11:51:19 scrappy Exp $
* $Id: lselect.h,v 1.4 1997/08/06 03:42:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -14,7 +14,7 @@
#define LSELECT_H
#include <stdio.h>
#include <access/htup.h>
#include "access/htup.h"
struct leftist {
short lt_dist; /* distance to leaf/empty node */
......@@ -24,17 +24,26 @@ struct leftist {
struct leftist *lt_right;
};
extern struct leftist *Tuples;
/* replaces global variables in lselect.c to make it reentrant */
typedef struct {
TupleDesc tupDesc;
int nKeys;
ScanKey scanKeys;
int sortMem; /* needed for psort */
} LeftistContextData;
typedef LeftistContextData *LeftistContext;
extern struct leftist *lmerge(struct leftist *pt, struct leftist *qt);
extern HeapTuple gettuple(struct leftist **treep, short *devnum);
extern int puttuple(struct leftist **treep, HeapTuple newtuple, int devnum);
extern void dumptuples(FILE *file);
extern int tuplecmp(HeapTuple ltup, HeapTuple rtup);
extern struct leftist *lmerge(struct leftist *pt, struct leftist *qt,
LeftistContext context);
extern HeapTuple gettuple(struct leftist **treep, short *devnum,
LeftistContext context);
extern void puttuple(struct leftist **treep, HeapTuple newtuple, short devnum,
LeftistContext context);
extern int tuplecmp(HeapTuple ltup, HeapTuple rtup, LeftistContext context);
#ifdef EBUG
extern void checktree(struct leftist *tree);
extern int checktreer(struct leftist *tree, int level);
extern void checktree(struct leftist *tree, LeftistContext context);
extern int checktreer(struct leftist *tree, int level, LeftistContext context);
#endif /* EBUG */
#endif /* LSELECT_H */
......@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: psort.h,v 1.3 1997/05/20 11:37:33 vadim Exp $
* $Id: psort.h,v 1.4 1997/08/06 03:42:13 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -14,11 +14,13 @@
#define PSORT_H
#include <stdio.h>
#include <access/relscan.h>
#include "access/relscan.h"
#include "utils/lselect.h"
#include "nodes/plannodes.h"
#define SORTMEM (1 << 18) /* 1/4 M - any static memory */
#define MAXTAPES 7 /* 7--See Fig. 70, p273 */
#define TAPEEXT "pg_psort.XXXXXX" /* TEMPDIR/TAPEEXT */
#define TAPEEXTLEN strlen("pg_psort.xxxxx.xxx") /* TEMPDIR/TAPEEXT */
#define FREE(x) pfree((char *) x)
struct tape {
......@@ -35,13 +37,38 @@ struct cmplist {
struct cmplist *cp_next; /* next in chain */
};
extern int Nkeys;
extern ScanKey key;
extern int SortMemory; /* free memory */
extern Relation SortRdesc;
extern struct leftist *Tuples;
/* This structure preserves the state of psort between calls from different
* nodes to its interface functions. Basically, it includes all of the global
* variables in psort. In case you were wondering, pointers to these structures
* are included in Sort node structures. -Rex 2.6.1995
*/
typedef struct Psortstate {
LeftistContextData treeContext;
int TapeRange;
int Level;
int TotalDummy;
struct tape Tape[MAXTAPES];
int BytesRead;
int BytesWritten;
int tupcount;
struct leftist *Tuples;
FILE *psort_grab_file;
long psort_current; /* could be file offset, or array index */
long psort_saved; /* could be file offset, or array index */
bool using_tape_files;
HeapTuple *memtuples;
} Psortstate;
#ifdef EBUG
#include <stdio.h>
#include "utils/elog.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#define PDEBUG(PROC, S1)\
elog(DEBUG, "%s:%d>> PROC: %s.", __FILE__, __LINE__, S1)
......@@ -69,15 +96,21 @@ if (1) CODE; else
#endif
/* psort.c */
extern void psort(Relation oldrel, Relation newrel, int nkeys, ScanKey key);
extern void initpsort(void);
extern bool psort_begin(Sort *node, int nkeys, ScanKey key);
extern void inittapes(Sort *node);
extern void resetpsort(void);
extern void initialrun(Relation rdesc);
extern bool createrun(HeapScanDesc sdesc, FILE *file);
extern HeapTuple tuplecopy(HeapTuple tup, Relation rdesc, Buffer b);
extern FILE *mergeruns(void);
extern void merge(struct tape *dest);
extern void endpsort(Relation rdesc, FILE *file);
extern void initialrun(Sort *node, bool *empty);
extern bool createrun(Sort *node, FILE *file, bool *empty);
extern HeapTuple tuplecopy(HeapTuple tup);
extern FILE *mergeruns(Sort *node);
extern void merge(Sort *node, struct tape *dest);
extern void dumptuples(Sort *node);
extern HeapTuple psort_grabtuple(Sort *node);
extern void psort_markpos(Sort *node);
extern void psort_restorepos(Sort *node);
extern void psort_end(Sort *node);
extern FILE *gettape(void);
extern void resettape(FILE *file);
extern void destroytape(FILE *file);
......
.\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here....
.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.5 1997/01/26 15:32:20 scrappy Exp $
.\" $Header: /cvsroot/pgsql/src/man/Attic/postgres.1,v 1.6 1997/08/06 03:42:18 momjian Exp $
.TH POSTGRES95 UNIX 12/08/96 Postgres95 Postgres95
.SH NAME
postgres \(em the Postgres backend server
......@@ -79,7 +79,10 @@ is the number of shared-memory buffers that the
.IR "postmaster"
has allocated for the backend server processes that it starts. If the
backend is running standalone, this specifies the number of buffers to
allocate. This value defaults to 64.
allocate. This value defaults to 64, and each buffer is 8k bytes.
.TP
.BR "-E"
Echo all queries.
.TP
.BR "-F"
Disable automatic fsync() call after each transaction.
......@@ -96,8 +99,10 @@ useful for interactive use.
.BR "-Q"
Specifies \*(lqquiet\*(rq mode.
.TP
.BR "-E"
Echo all queries.
.BR "-S"
Specifies the amount of memory to be used by internal sorts before using
disk files for sorting. This value is specified in 1k bytes, and
defaults to 512.
.TP
.BR "-e"
The
......@@ -154,15 +159,6 @@ Turns off the locking system.
.BR "-N"
Disables use of newline as a query delimiter.
.TP
.BR "-S"
Indicates that the transaction system can run with the assumption of
stable main memory, thereby avoiding the necessary flushing of data
and log pages to disk at the end of each transaction system. This is
only used for performance comparisons for stable vs. non-stable
storage. Do not use this in other cases, as recovery after a system
crash may be impossible when this option is specified in the absence
of stable main memory.
.TP
.BR "-b"
Enables generation of bushy query plan trees (as opposed to left-deep
query plans trees). These query plans are not intended for actual
......
.\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here....
.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.5 1997/02/19 01:31:30 momjian Exp $
.\" $Header: /cvsroot/pgsql/src/man/Attic/postmaster.1,v 1.6 1997/08/06 03:42:21 momjian Exp $
.TH POSTMASTER UNIX 11/05/95 PostgreSQL PostgreSQL
.SH "NAME"
postmaster \(em run the Postgres postmaster
......@@ -60,7 +60,7 @@ understands the following command-line options:
is the number of shared-memory buffers for the
.IR "postmaster"
to allocate and manage for the backend server processes that it
starts. This value defaults to 64.
starts. This value defaults to 64, and each buffer is 8k bytes.
.TP
.BR "-D" " data_dir"
Specifies the directory to use as the root of the tree of database
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment