通过 libpqxx 提高对 PostgreSQL 数据库的更新速度
Increase the update speed to PostgreSQL database via libpqxx
我正在尝试使用 libpqxx 库通过 C++ 读取和写入 postgreSQL 数据库。
我拥有的示例数据库是 3 列和大约 16000 行。
在我的代码中,我使用 work.exec 传输 sql 查询,并且用了 30 多秒来更新 1 列中的所有 16000 个单元格。
不知道是不是我写的不对,还是写入时间取决于我的硬盘速度?
附上我使用的示例代码
#include <string>
#include <vector>
#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>
#include <pqxx/pqxx>
using namespace std;
using namespace std::chrono;
auto start = high_resolution_clock::now();
int main(int argc, char* argv[])
{
//open connection to postgresql database
pqxx::connection con("host=localhost port=5432 dbname=postgres user=postgres password=P@$$w0rd");
//"pqxx::work" is an transaction type object in libpqxx, use to transfer SQL query or command
pqxx::work wrk(con);
//"pqxx:result" set containing data returned by a query or command
pqxx::result res = wrk.exec("SELECT * FROM signal");
for (int i = 0; i < res.size(); i++)
{
wrk.exec("UPDATE public.signal SET signalvalue = signalvalue + 1 WHERE indexid ="+to_string(i)+";");
}
wrk.commit();
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function: " << duration.count() << " microseconds" << endl;
cin.get();
return 0;
}
您必须在单个事务中 运行 UPDATE
语句。 PostgreSQL 在自动提交模式下工作,因此您的每个 UPDATE
s 都在其自己的事务中 运行ning。对事务日志的 16000 次刷新会让你丧命。
以 START TRANSACTION
开始显式事务并以 COMMIT
结束。
除了性能方面的考虑,这是一个好主意,因为这样数据修改是原子的,也就是说,如果其中任何一个失败,所有 UPDATE
都将被撤消。
使用准备好的语句可以提高代码的性能。
来自 libpqxx 文档
If you have an SQL statement that you're going to execute many times in quick succession, it may be more efficient to prepare it once and reuse it. This saves the database backend the effort of parsing complex SQL and figuring out an efficient execution plan. Another nice side effect is that you don't need to worry about escaping parameters.
你的 SQL 语句看起来像
UPDATE public.signal SET signalvalue = signalvalue + 1 WHERE indexid =
您可以准备一次,然后在循环中为 $1 插入不同的值。
The libpqxx documentation有例子可以参考。
我正在尝试使用 libpqxx 库通过 C++ 读取和写入 postgreSQL 数据库。 我拥有的示例数据库是 3 列和大约 16000 行。
在我的代码中,我使用 work.exec 传输 sql 查询,并且用了 30 多秒来更新 1 列中的所有 16000 个单元格。 不知道是不是我写的不对,还是写入时间取决于我的硬盘速度?
附上我使用的示例代码
#include <string>
#include <vector>
#include <chrono>
#include <iostream>
#include <fstream>
#include <sstream>
#include <pqxx/pqxx>
using namespace std;
using namespace std::chrono;
auto start = high_resolution_clock::now();
int main(int argc, char* argv[])
{
//open connection to postgresql database
pqxx::connection con("host=localhost port=5432 dbname=postgres user=postgres password=P@$$w0rd");
//"pqxx::work" is an transaction type object in libpqxx, use to transfer SQL query or command
pqxx::work wrk(con);
//"pqxx:result" set containing data returned by a query or command
pqxx::result res = wrk.exec("SELECT * FROM signal");
for (int i = 0; i < res.size(); i++)
{
wrk.exec("UPDATE public.signal SET signalvalue = signalvalue + 1 WHERE indexid ="+to_string(i)+";");
}
wrk.commit();
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function: " << duration.count() << " microseconds" << endl;
cin.get();
return 0;
}
您必须在单个事务中 运行 UPDATE
语句。 PostgreSQL 在自动提交模式下工作,因此您的每个 UPDATE
s 都在其自己的事务中 运行ning。对事务日志的 16000 次刷新会让你丧命。
以 START TRANSACTION
开始显式事务并以 COMMIT
结束。
除了性能方面的考虑,这是一个好主意,因为这样数据修改是原子的,也就是说,如果其中任何一个失败,所有 UPDATE
都将被撤消。
使用准备好的语句可以提高代码的性能。
来自 libpqxx 文档
If you have an SQL statement that you're going to execute many times in quick succession, it may be more efficient to prepare it once and reuse it. This saves the database backend the effort of parsing complex SQL and figuring out an efficient execution plan. Another nice side effect is that you don't need to worry about escaping parameters.
你的 SQL 语句看起来像
UPDATE public.signal SET signalvalue = signalvalue + 1 WHERE indexid =
您可以准备一次,然后在循环中为 $1 插入不同的值。
The libpqxx documentation有例子可以参考。