C++、Postgres、libpqxx大型查询
C++, Postgres , libpqxx huge query
我必须通过以下代码执行对Postgres的SQL查询。查询返回大量行(40M或更多),并有4个整数字段:当我使用32Gb的工作站时,一切都正常,但在16Gb的工作站上,查询非常慢(我想是由于交换)。有没有什么方法可以告诉C++在不等待整个数据集的情况下批量加载行?对于Java,我以前从未遇到过这些问题,因为可能有更好的JDBC驱动程序。
try {
work W(*Conn);
result r = W.exec(sql[sqlLoad]);
W.commit();
for (int rownum = 0; rownum < r.size(); ++rownum) {
const result::tuple row = r[rownum];
vid1 = row[0].as<int>();
vid2 = row[1].as<int>();
vid3 = row[2].as<int>();
.....
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
我正在使用PostgreSQL 9.3,在那里我看到了http://www.postgresql.org/docs/9.3/static/libpq-single-row-mode.html,但我不知道如何在我的C++代码中使用它。我们将感谢您的帮助。
编辑:此查询只运行一次,用于创建必要的主内存数据结构。因此,tt无法优化。此外,pgAdminIII可以在不到一分钟的时间内,在相同(或RAM较小)的PC上轻松地获取这些行。此外,Java可以轻松地处理两倍的行数(使用Statent.setFetchSize()http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#setFetchSize%28int%29)因此,这实际上是libpqxx库的问题,而不是应用程序的问题。有没有一种方法可以在C++中强制执行此功能,而无需手动明确设置限制/偏移?
使用光标?
另请参阅FETCH。我想,光标会在幕后为您使用它,但以防万一,您总是可以使用FETCH手动编码流式检索。
为了回答我自己的问题,我修改了如何使用libpqxx中的pqxx::stateless_cursor类?
try {
work W(*Conn);
pqxx::stateless_cursor<pqxx::cursor_base::read_only, pqxx::cursor_base::owned>
cursor(W, sql[sqlLoad], "mycursor", false);
/* Assume you know total number of records returned */
for (size_t idx = 0; idx < countRecords; idx += 100000) {
/* Fetch 100,000 records at a time */
result r = cursor.retrieve(idx, idx + 100000);
for (int rownum = 0; rownum < r.size(); ++rownum) {
const result::tuple row = r[rownum];
vid1 = row[0].as<int>();
vid2 = row[1].as<int>();
vid3 = row[2].as<int>();
.............
}
}
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
光标是一个很好的起点。下面是另一个光标示例,使用do-while()
const std::conStr("user=" + opt::dbUser + " password=" + opt::dbPasswd + " host=" + opt::dbHost + " dbname=" + opt::dbName);
pqxx::connection conn(connStr);
pqxx::work txn(conn);
std::string selectString = "SELECT id, name FROM table_name WHERE condition";
pqxx::stateless_cursor<pqxx::cursor_base::read_only, pqxx::cursor_base::owned>
cursor(txn, selectString, "myCursor", false);
//cursor variables
size_t idx = 0; //starting location
size_t step = 10000; //number of rows for each chunk
pqxx::result result;
do{
//get next cursor chunk and update the index
result = cursor.retrieve( idx, idx + step );
idx += step;
size_t records = result.size();
cout << idx << ": records pulled = " << records << endl;
for( pqxx::result::const_iterator row : result ){
//iterate over cursor rows
}
}
while( result.size() == step ); //if the result.size() != step, we're on our last loop
cout << "Done!" << endl;
我正在我的应用程序中迭代大约3300万行。除了使用光标之外,我还使用了以下方法:
- 将数据分割成更小的块。对我来说,那就是使用边界框来获取给定区域中的数据
- 构造一个查询来获取chunk,并使用光标对其进行迭代
- 将块存储在一旦处理完给定大块
我知道这是一个很晚才回答你的问题,但我希望这可能会帮助到别人!
- Mongodb c++驱动程序:如何查询元素的数组
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C++中高效的大型稀疏块压缩线性方程
- 查询SQLite数据库中的日期
- 如何在ArangoDb AQL查询中指定数据库
- Qt SQLite没有查询或参数计数不匹配
- 如何使用c++在VS 2019上运行SQL查询
- 从返回的顶点缓冲区查询顶点结构
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- LMDB:在有限的内存系统中打开大型数据库
- 如何在大型c++项目的可视化代码中设置调试
- 仅在大型阵列上出现合并排序分段错误
- 在堆栈上C++大型多维数组
- 查询 NFS 上的提升进程间::file_lock
- Qt JSON – 从子项查询
- atoi() 在应用于大型命令行参数时会产生不正确的值
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- C++、Postgres、libpqxx大型查询