What is your advice on configuring PostgreSQL such that BLOB can be written quickly?
We are using PostgreSQL to insert BLOB at a high rate.
- We call a lo_write() roughly 220 times a second.
- We write roughly 30KB of binary data per lo_write().
- This is equivalent to roughly 6 MB/s.
Our computer is RAID-5, so the write speed is in the neighborhood of 200 MB/s.
We have already tuned the postgresql.conf to have the following:
- we changed shared_buffers = 1GB
- we turned off fsync
- logging_collector = off (pretty much everything related to logging is off)
We have made sure that if we don't store BLOB as part of our INSERT query, then PgSql keeps up fine. It's only when we store BLOB as part of our query that it slows down.
EDIT: I'm using Windows XP/Server. I'm using Pgsql 8.3 with PostGIS 1.3.6. The reason why I needed to store BLOB in the DB is because my application requires me to search for these BLOBs in real-time.
Background: Our application is high-performance real-time signal processing, where we store our signals into the database as BLOB.
EDIT: This is the C++ code that we used to perform the benchmark. Apparently, we are getting about 16 MB/s on our RAID config.
#include "libpq-fe.h"
#include "libpq/libpq-fs.h"
#include <sstream>
#include <iostream>
#include <tbb/tick_count.h>
void test()
{
std::stringstream stst;
stst << "user=postgres password=1234 dbname=test_db";
PGconn* conn = PQconnectdb(stst.str().c_str());
if (PQstatus(conn) != CONNECTION_OK)
{
throw std::exception("failed to connect To DB engine: ");
}
const int dataSize = 18512;
char* data = (char*) malloc( dataSize );
const int count = 10000;
tbb::tick_count t0 = tbb::tick_count::now();
for( int idx = 0; idx < count; idx++ )
{
// Insert acoustic binary into large object table "pg_largeobject"
Oid objectId;
int lobj_fd;
PGresult *res;
res = PQexec(conn, "begin");
PQclear(res);
objectId = lo_creat(conn, INV_READ|INV_WRITE);
if (objectId == 0)
{
throw std::exception("AddAcousticTable: Cannot create large object\n");
}
lobj_fd = lo_open(conn, objectId, INV_WRITE);
const unsigned int writeBytes = lo_write(conn, lobj_fd, data, dataSize );
if (writeBytes != dataSize )
{
std::stringstream msg;
msg << "PsSasDataDB::AddToAcousticTable(): Incorrect number of bytes written for large object ";
msg << writeBytes;
throw std::exception(msg.str().c_str());
}
lo_close(conn, lobj_fd);
res = PQexec(conn, "end");
PQclear(res);
}
tbb::tick_count t1 = tbb::tick_count::now();
std::cout << "Performance: " << (double(count*dataSize)/(t1-t0).seconds())/(1024.0*1024.0) << " MB/seconds";
free( data );
}
int main()
{
try
{
test();
}
catch( std::exception e )
{
std::cerr << e.what();
}
return 0;
}