提交 e0bd6017 编写于 作者: T Tom Lane

Rearrange coding in COPY so that expansible string buffer for data being

read is reused for successive attributes, instead of being deleted and
recreated from scratch for each value read in.  This reduces palloc/pfree
overhead a lot.  COPY IN still seems to be noticeably slower than it was
in 6.5 --- we need to figure out why.  This change takes care of the only
major performance loss I can see in copy.c itself, so the performance
problem is at a lower level somewhere.
上级 d00391e7
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.95 2000/01/14 22:11:33 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.96 2000/01/16 21:37:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -66,6 +66,21 @@ static int CountTuples(Relation relation); ...@@ -66,6 +66,21 @@ static int CountTuples(Relation relation);
static int lineno; static int lineno;
static bool fe_eof; static bool fe_eof;
/*
* These static variables are used to avoid incurring overhead for each
* attribute processed. attribute_buf is reused on each CopyReadAttribute
* call to hold the string being read in. Under normal use it will soon
* grow to a suitable size, and then we will avoid palloc/pfree overhead
* for subsequent attributes. Note that CopyReadAttribute returns a pointer
* to attribute_buf's data buffer!
* encoding, if needed, can be set once at the start of the copy operation.
*/
static StringInfoData attribute_buf;
#ifdef MULTIBYTE
static int encoding;
#endif
/* /*
* Internal communications functions * Internal communications functions
*/ */
...@@ -276,6 +291,14 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, ...@@ -276,6 +291,14 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
"directly to or from a file. Anyone can COPY to stdout or " "directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone."); "from stdin. Psql's \\copy command also works for anyone.");
/*
* Set up variables to avoid per-attribute overhead.
*/
initStringInfo(&attribute_buf);
#ifdef MULTIBYTE
encoding = pg_get_client_encoding();
#endif
if (from) if (from)
{ /* copy from file to database */ { /* copy from file to database */
if (rel->rd_rel->relkind == RELKIND_SEQUENCE) if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
...@@ -337,6 +360,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, ...@@ -337,6 +360,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
} }
CopyTo(rel, binary, oids, fp, delim, null_print); CopyTo(rel, binary, oids, fp, delim, null_print);
} }
if (!pipe) if (!pipe)
{ {
FreeFile(fp); FreeFile(fp);
...@@ -348,6 +372,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, ...@@ -348,6 +372,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
if (IsUnderPostmaster) if (IsUnderPostmaster)
pq_endcopyout(false); pq_endcopyout(false);
} }
pfree(attribute_buf.data);
/* /*
* Close the relation. If reading, we can release the AccessShareLock * Close the relation. If reading, we can release the AccessShareLock
...@@ -717,7 +742,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null ...@@ -717,7 +742,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
loaded_oid = oidin(string); loaded_oid = oidin(string);
if (loaded_oid < BootstrapObjectIdData) if (loaded_oid < BootstrapObjectIdData)
elog(ERROR, "COPY TEXT: Invalid Oid. line: %d", lineno); elog(ERROR, "COPY TEXT: Invalid Oid. line: %d", lineno);
pfree(string);
} }
} }
for (i = 0; i < attr_count && !done; i++) for (i = 0; i < attr_count && !done; i++)
...@@ -727,8 +751,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null ...@@ -727,8 +751,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
{ {
values[i] = PointerGetDatum(NULL); values[i] = PointerGetDatum(NULL);
nulls[i] = 'n'; nulls[i] = 'n';
if (string)
pfree(string);
} }
else if (string == NULL) else if (string == NULL)
done = 1; done = 1;
...@@ -745,7 +767,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null ...@@ -745,7 +767,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
if (!PointerIsValid(values[i]) && if (!PointerIsValid(values[i]) &&
!(rel->rd_att->attrs[i]->attbyval)) !(rel->rd_att->attrs[i]->attbyval))
elog(ERROR, "copy from line %d: Bad file format", lineno); elog(ERROR, "copy from line %d: Bad file format", lineno);
pfree(string);
} }
} }
if (!done) if (!done)
...@@ -1115,9 +1136,10 @@ CopyReadNewline(FILE *fp, int *newline) ...@@ -1115,9 +1136,10 @@ CopyReadNewline(FILE *fp, int *newline)
/* /*
* Read the value of a single attribute. * Read the value of a single attribute.
* *
* Result is either a palloc'd string, or NULL (if EOF or a null attribute). * Result is either a string, or NULL (if EOF or a null attribute).
* *isnull is set true if a null attribute, else false. * Note that the caller should not pfree the string!
* *
* *isnull is set true if a null attribute, else false.
* delim is the string of acceptable delimiter characters(s). * delim is the string of acceptable delimiter characters(s).
* *newline remembers whether we've seen a newline ending this tuple. * *newline remembers whether we've seen a newline ending this tuple.
* null_print says how NULL values are represented * null_print says how NULL values are represented
...@@ -1126,19 +1148,20 @@ CopyReadNewline(FILE *fp, int *newline) ...@@ -1126,19 +1148,20 @@ CopyReadNewline(FILE *fp, int *newline)
static char * static char *
CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print) CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print)
{ {
StringInfoData attribute_buf;
char c; char c;
#ifdef MULTIBYTE #ifdef MULTIBYTE
int mblen; int mblen;
int encoding;
unsigned char s[2]; unsigned char s[2];
char *cvt; char *cvt;
int j; int j;
encoding = pg_get_client_encoding();
s[1] = 0; s[1] = 0;
#endif #endif
/* reset attribute_buf to empty */
attribute_buf.len = 0;
attribute_buf.data[0] = '\0';
/* if last delimiter was a newline return a NULL attribute */ /* if last delimiter was a newline return a NULL attribute */
if (*newline) if (*newline)
{ {
...@@ -1148,8 +1171,6 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_ ...@@ -1148,8 +1171,6 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
*isnull = (bool) false; /* set default */ *isnull = (bool) false; /* set default */
initStringInfo(&attribute_buf);
if (CopyGetEof(fp)) if (CopyGetEof(fp))
goto endOfFile; goto endOfFile;
...@@ -1265,17 +1286,20 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_ ...@@ -1265,17 +1286,20 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_
attribute_buf.len); attribute_buf.len);
if (cvt != attribute_buf.data) if (cvt != attribute_buf.data)
{ {
pfree(attribute_buf.data); /* transfer converted data back to attribute_buf */
return cvt; attribute_buf.len = 0;
attribute_buf.data[0] = '\0';
appendBinaryStringInfo(&attribute_buf, cvt, strlen(cvt));
pfree(cvt);
} }
#endif #endif
if (strcmp(attribute_buf.data, null_print)==0) if (strcmp(attribute_buf.data, null_print)==0)
*isnull = true; *isnull = true;
return attribute_buf.data; return attribute_buf.data;
endOfFile: endOfFile:
pfree(attribute_buf.data);
return NULL; return NULL;
} }
...@@ -1286,13 +1310,11 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim) ...@@ -1286,13 +1310,11 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
char c; char c;
#ifdef MULTIBYTE #ifdef MULTIBYTE
char *string_start; char *string_start;
int encoding;
int mblen; int mblen;
int i; int i;
#endif #endif
#ifdef MULTIBYTE #ifdef MULTIBYTE
encoding = pg_get_client_encoding();
string = (char *) pg_server_to_client((unsigned char *) server_string, string = (char *) pg_server_to_client((unsigned char *) server_string,
strlen(server_string)); strlen(server_string));
string_start = string; string_start = string;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册