我正在尝试使用libpqxx库通过C ++读写postgreSQL数据库。我拥有的示例数据库是3列,大约16000行。
在我的代码中,我使用work.exec来传递sql查询,并且花了30 + sec来更新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
都在自己的事务中运行。 16000刷新到事务日志是杀死您的原因。
以START TRANSACTION
开始显式事务,以COMMIT
结束。
除了性能方面的考虑外,这是一个好主意,因为通过这种方式,数据修改是原子的,也就是说,如果其中任何一个失败,所有的UPDATE
都将被撤消。
可以通过使用准备好的语句来提高代码的性能。
来自libpqxx文档
如果您有一条要快速连续执行多次的SQL语句,则准备一次并重用它可能会更有效。这样可以节省数据库后端解析复杂SQL和确定有效执行计划的工作量。另一个不错的副作用是,您不必担心转义参数。
您的SQL语句看起来像
UPDATE public.signal SET signalvalue = signalvalue + 1 WHERE indexid = $1
您可以准备一次,然后在循环中为$ 1插入不同的值。
The libpqxx documentation有一个示例可以参考。