Bas*_*ond 5 c++ database oracle qt
我有一个项目涉及将 Oracle 数据库集成到 Qt 桌面应用程序中。由于 Qt 有一个非常易于使用的数据库交互界面,因此我编译了 QOCI 驱动程序来支持 Oracle 连接。
一切工作正常,但查询的处理时间非常慢。我怎样才能提高性能?
我处理任意查询的代码如下所示:
QList< QList<QString> > DBWrapper::executeQuery(QString const& queryString)
{
QList< QList<QString> > results;
if (_db.isOpen()) {
QSqlQuery qry(queryString);
if(qry.exec()) {
while(qry.next()) {
QList<QString> row;
results.append(row);
for(int i = 0; i < qry.record().count(); ++i) {
results.last().append(qry.value(i).toString());
}
}
} else {
qDebug() << queryString;
qDebug() << "FAILURE: cannot handle query.";
qDebug() << " > " << qry.lastError();
}
} else {
qDebug() << "Error Opening Database = " << _db.lastError();
}
return results;
}
Run Code Online (Sandbox Code Playgroud)
有一些资源描述了 Qt 中其他 DBMS 的相同问题。他们所有人都建议添加qry.setForwardOnly(true)和qry.prepare(queryString);添加到查询设置中。
虽然,这看起来是阅读 Qt 文档的良好风格,但它几乎没有给我带来任何改进。调试代码时我运行了一些速度测试,减少了所有内容,只是为了测量 QSql 内容的运行时间。
//...
QSqlQuery qry(queryString);
qry.setForwardOnly(true);
qry.prepare(queryString);
QElapsedTimer timer;
timer.start();
if(qry.exec()) {
qDebug() << "time to execute query: " << timer.elapsed() << "ms";
timer.start();
while(qry.next()) {
// don't do anything here
}
qDebug() << "time to iterate through query results: " << timer.elapsed() << "ms";
}
Run Code Online (Sandbox Code Playgroud)
事实证明,执行查询的时间不到 50 毫秒,而迭代结果大约花费了 3000 毫秒,SELECT 语句的结果中只有 100 个元素。
解决方案很难找到,但看起来相当简单。设置数据库连接时,您可以定义特定于您正在使用的 DBMS 类型的连接选项。OCI 定义OCI_ATTR_PREFETCH_ROWS,默认为 1。设置较高的值可快速提高迭代速度。
_db = QSqlDatabase::addDatabase("QOCI");
_db.setHostName(host);
_db.setDatabaseName(dbName);
_db.setPort(port);
_db.setUserName(user);
_db.setPassword(pwd);
_db.setConnectOptions("OCI_ATTR_PREFETCH_ROWS=1000");
_db.open();
Run Code Online (Sandbox Code Playgroud)
如果我错了,请有人纠正我,但我猜测每个选择查询都会在 Qt 的底层存储结构中缓存最大数量的行。我相信这个数字等于 的值OCI_ATTR_PREFETCH_ROWS。由于qry.value(...)仅指向一行(QSqlRecord),我假设这OCI_ATTR_PREFETCH_ROWS = 1意味着在每个qry.next()数据库上将以某种方式在内部再次查询以移动该游标。这会完全破坏性能,就像对我一样。
我希望像我一样面临这个问题的人能够找到这篇文章。