gpt4 book ai didi

c++ - 简单的 Postgresql libpq 代码太慢?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:16:31 25 4
gpt4 key购买 nike

我正在使用 libpq 开发 postgresql。下面给出的代码花费了大量时间(代码末尾给出的时间)。

#include "stdafx.h"
#include <stdlib.h>
#include <libpq-fe.h>
#include <windows.h>

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

int _tmain(int argc, _TCHAR* argv[])
{
const TCHAR *conninfo;
PGconn *conn;
PGresult *res;
int nFields, i, j;

if (argc > 1)
conninfo = argv[1];
else
conninfo = _T("hostaddr=192.168.4.171 port=12345 dbname=mydb user=myname password=mypass");

conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
exit_nicely(conn);
}

/* 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(conn);
}

TCHAR szVal1[200];
TCHAR szVal2[200];
TCHAR szBuffer[200];

TCHAR *paramValues[2];
int paramLengths[2];
int paramFormats[2] = {0,0};

ExecStatusType eStatus;

LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
double dAppFreq = double(li.QuadPart)/1000.0;

QueryPerformanceCounter(&li);
LONGLONG siStartCounter = li.QuadPart;

TCHAR szStmt[512] = {0};
_tcscpy_s(szStmt, 512, _T("Insert50k"));
Oid oidTypes[2] = {0,0};

PGresult *pRes = PQprepare(conn,
szStmt,
_T("insert into details values($1,$2);"),
2,
oidTypes);
QueryPerformanceCounter(&li);
LONGLONG siEndCounter = li.QuadPart;
LONGLONG siLoop = 0;

double dDiff = (siEndCounter - siStartCounter)/dAppFreq;
printf("Prepared %.2lf\n", dDiff);

for(int i=0; i<50000; i++)
{
_stprintf_s(szVal1, 200, _T("%d"), i);
_stprintf_s(szVal2, 200, _T("Detail%d"), i);

paramValues[0] = szVal1;
paramValues[1] = szVal2;

paramLengths[0] = _tcslen(szVal1);
paramLengths[1] = _tcslen(szVal2);

siStartCounter = siEndCounter;
pRes = PQexecPrepared(conn,
szStmt,
2,
paramValues,
paramLengths,
paramFormats,
0);
QueryPerformanceCounter(&li);
siEndCounter = li.QuadPart;
siLoop += (siEndCounter - siStartCounter);

eStatus = PQresultStatus(res);
if (!res || (eStatus != PGRES_COMMAND_OK) )
{
PQclear(res);
exit_nicely(conn);
}
}

dDiff = siLoop/dAppFreq;
printf("Inserted %.2lf\n", dDiff);

siStartCounter = siEndCounter;


_tcscpy_s(szBuffer,200, _T("select count(*) from programdetails;"));
res = PQexec(conn, szBuffer);

eStatus = PQresultStatus(res);
if (!res || (eStatus != PGRES_TUPLES_OK) )
{
PQclear(res);
exit_nicely(conn);
}

/* first, print out the attribute names */
nFields = PQnfields(res);
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i));
printf("\n\n");

/* next, print out the rows */
for (i = 0; i < PQntuples(res); i++)
{
for (j = 0; j < nFields; j++)
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
}

QueryPerformanceCounter(&li);
siEndCounter = li.QuadPart;
dDiff = (siEndCounter - siStartCounter)/dAppFreq;
printf("Printed %.2lf\n", dDiff);

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

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

return 0;
}

示例输出(以毫秒为单位):

Prepared 0.55
Inserted 5527.52
count

50000
Printed 7.58

这里的查询是先准备,再执行。这个简单的插入大约需要 5.5 秒。有没有更好的方法来做同样的事情,还是我做错了什么?

最佳答案

在 TCP 连接上,每个 INSERT 都会导致到数据库的 TCP 往返。在 5.5 秒内完成 50000 次插入意味着一次 TCP 往返需要大约 0.1 毫秒。您必须将其与您的网络设备的 TCP 基准进行比较,但您可能不能指望使用这种方法会更快。

您应该考虑使用 COPY FROM STDIN 而不是单独的 INSERT。在内部,这将缓冲内容,并且由于与服务器的往返次数大大减少,您可能会看到速度显着提高。

参见 http://www.postgresql.org/docs/current/static/libpq-copy.html用于与这种形式的 COPY 相关的 libpq API。

关于c++ - 简单的 Postgresql libpq 代码太慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10510539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com