Re: Postgres insert performance and storage requirement compared to Oracle

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Oct 27, 2010 at 08:00, Divakar Singh <dpsmails@xxxxxxxxx> wrote:
> I am attaching my code below.
> Is any optimization possible in this?
> Do prepared statements help in cutting down the insert time to half for this
> kind of inserts?

In half? not for me.  Optimization possible? Sure, using the code you
pasted (time ./a.out 100000 <method>):
PQexec: 41s
PQexecPrepared: 36s
1 insert statement: 7s
COPY: 1s
psql: 256ms

Basically the above echoes the suggestions of others, use COPY if you can.

Find the source for the above attached.  Its just a very quick
modified version of what you posted. [ disclaimer the additions I
added are almost certainly missing some required error checking... ]

[ psql is fast because the insert is really dumb: insert into aaaa (a,
b, c, d, e, f, g, h, j, k, l, m, n, p) select 1, 'asdf', 'asdf',
'asdf', 'asdf', 'asdf', 'asdf', 'asdf', 'asdf', 'asdf', 'asdf',
'asdf', 'asdf', 'asdf' from generate_series(1, 100000); ]
//----------------------------------------------------------------------------------------------------------------------------
/*
 * testlibpq.c
 *
 *	  Test the C version of libpq, the PostgreSQL frontend library.
 */
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <iostream>
using namespace std;
#include <string.h>
#include <stdio.h>
#include <time.h>

PGconn	 *conn;
int howmany=0;

static void
exit_nicely(void)
{
	PQfinish(conn);
	exit(1);
}

static void
pgexec(void)
{
	printf("using PQexec\n");

	char query[1024]={0};
	for(int i=0; i<howmany;i++)
	{
		PGresult   *res;

		sprintf (query, "INSERT INTO aaaa(a, b, c, d, e, f, g, h, j, k, l, m, n, p) VALUES (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA')", i);
		res = PQexec(conn, query);
		if(PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			cout<<"error at iteration "<<i<<":"<<PQresultErrorMessage(res)<<endl;
			PQclear(res);
			break;
		}
		PQclear(res);
	}
}

static void
pgprepare(void)
{
	printf("using PQprepare\n");

	PGresult *res = PQprepare(conn, "my_insert", "INSERT INTO aaaa(a, b, c, d, e, f, g, h, j, k, l, m, n, p) VALUES (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, $1, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA')", 1, NULL);
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "insert command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	char **vals = (char**)calloc(1, sizeof(char *));
	if(!vals)
		abort();
	vals[0] = (char*)calloc(10, sizeof(char));
	if(!vals[0])
		abort();

	for (int i=0; i<howmany;i++)
	{
		sprintf(vals[0], "%d", i);
		res = PQexecPrepared(conn, "my_insert", 1, vals, NULL, NULL, 0);

		if(PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			cout<<"error at iteration "<<i<<":"<<PQresultErrorMessage(res)<<endl;
			PQclear(res);
			break;
		}
		PQclear(res);
	}

	free(vals[0]);
	free(vals);
}

static void
pginsert(void)
{
	printf("using one insert command\n");

	const char *line = " (67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA'),";
	const char *cmd = "insert into aaaa (a, b, c, d, e, f, g, h, j, k, l, m, n, p) values ";
	char *start;
	char *query = (char*)calloc(strlen(cmd) + ((howmany+1) * (strlen(line)+40)) + 1, sizeof(char));
	if(!query)
		abort();

	start = query;
	query += sprintf(query, cmd);

	for(int i=0; i<howmany; i++)
		query += sprintf(query, line, i);

	// chop off last comma
	query[-1] = 0;

	PGresult *res = PQexec(conn, start);
	if(PQresultStatus(res) != PGRES_COMMAND_OK)
		cout<<"error "<<PQresultErrorMessage(res)<<endl;
	PQclear(res);

	free(start);
}

static void
pgcopy(void)
{
	printf("using copy\n");

	char query[1024]={0};
	PGresult *res = PQexec(conn, "copy aaaa from STDIN delimiter \',\';");
	if(PQresultStatus(res) != PGRES_COPY_IN)
	{
		fprintf(stderr, "insert command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	for(int i=0; i<howmany;i++)
	{
		sprintf(query, "67, 'ABRAKADABRA', 'ABRAKADABRA', 'ABRAKADABRA', '1-Dec-2010', 'ABRAKADABRA', 'ABRAKADABRA',  'ABRAKADABRA', '1-Dec-2010', 99999, 99999, %d, 9999, 'ABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRAABRAKADABRA\n", i);
		if(PQputCopyData(conn, query, strlen(query)) != 1)
		{
			cout<<"error at iteration "<<i<<":"<<PQerrorMessage(conn)<<endl;
			break;
		}
	}

	if(PQputCopyEnd(conn, NULL) != 1)
		cout<<"error: "<<PQerrorMessage(conn)<<endl;
}

int
main(int argc, char **argv)
{
	const char *conninfo = "host=192.168.0.15 dbname=whopper port=5432 user=docsysweb password=docsyswebchaos" ;
	PGresult   *res;
	char type;
	if (argc<3)
	{
		cout<<"usage: <# to insert> <method: PQ(e)xec, PQexec(P)repared, one (I)nsert, (C)OPY>"<<endl;
		return -1;
	}
	sscanf(argv[1], "%d", &howmany);
	sscanf(argv[2], "%c", &type);

	time_t startt = time(0);
	cout<<"starting at "<<asctime(localtime(&startt));
	cout<<"inserting "<<howmany<<" records"<<endl;

	/* Make a connection to the database */
	conn = PQconnectdb(conninfo);

	/* Check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "Connection to database failed: %s",
				PQerrorMessage(conn));
		exit_nicely();
	}

	/* Start a transaction block */
	res = PQexec(conn, "BEGIN");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely();
	}
	PQclear(res);

	switch(type)
	{
		case 'e':
			pgexec();
			break;
		case 'p':
			pgprepare();
			break;
		case 'i':
			pginsert();
			break;
		case 'c':
			pgcopy();
			break;
		default:
			fprintf(stderr, "Dont know how to '%c'\n", type);
			exit_nicely();
			break;
	}

	/* end the transaction */
	res = PQexec(conn, "END");
	PQclear(res);

	time_t endt = time(0);
	cout<<"Finished at "<<asctime(localtime(&endt))<<"total: "<< endt - startt <<"s"<<endl;


	/* close the connection to the database and cleanup */
	PQfinish(conn);

	return 0;
}



//----------------------------------------------------------------------------------------------------------------------------

-- 
Sent via pgsql-performance mailing list (pgsql-performance@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

[Postgresql General]     [Postgresql PHP]     [PHP Users]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Yosemite]

  Powered by Linux