我必须通过以下代码对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 ++代码中使用它。您的帮助将不胜感激。
EDIT:此查询仅运行一次,以创建必要的主内存数据结构。因此,无法优化tt。同样,pgAdminIII可以在一分钟之内轻松地在相同(或RAM较小)的PC上获取这些行。而且,Java可以轻松处理两倍的行数(使用Statent.setFetchSize()http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#setFetchSize%28int%29)。因此,这实际上是libpqxx库的问题,而不是应用程序的问题。有没有一种方法可以在C ++中强制执行此功能,而无需手动明确设置限制/偏移量?
为了回答我自己的问题,我改编了How to use pqxx::stateless_cursor class from libpqxx?
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万行。除了使用游标之外,我还使用以下方法:
我知道这是您问题的很晚答案,但我希望这对某人有帮助!