为什么我的 sqlite 查询在 Qt5 中这么慢?
Why is my sqlite query so slow in Qt5?
在 Qt5.4 中使用 QSqlDatabase 和 sqlite3 在 Ubuntu14 .04 64 位:
首先我在数据库上打开并调用 transaction()
。
接下来我进行 54 个单独的插入查询,每个都准备好,每个都在执行后删除。
最后我打电话给commit()
。
所有调用都完成且没有错误,但执行时间仍然很糟糕(54 次微不足道的插入总共耗时约 500 毫秒)。
我的电脑相当现代,配备了条带化 SSD 磁盘以提高性能。使用 Sqliteman 访问 sqlite 文件时,速度非常快。
那么这是怎么回事?
插入内容如下:
void BottleRigStorage::upsertTag(Tag &tag){
//ScopedTimer st("query time for tag");
if(open()){
QSqlQuery query(db);
query.prepare("INSERT OR REPLACE INTO tags ("
" id"
", batchID"
", retries"
", good"
", status"
", color"
", firstCheckTimestamp"
", createdTimestamp"
", modifiedTimestamp"
", fulfilledTimestamp"
") VALUES ("
" :id"
", :batchID"
", :retries"
", :good"
", :status"
", :color"
", :firstCheckTimestamp"
", :createdTimestamp"
", :modifiedTimestamp"
", :fulfilledTimestamp"
");");
query.bindValue(":id", tag.id);//8 chars
query.bindValue(":batchID", tag.batchID);//8 chars
query.bindValue(":retries", tag.retries);//int
query.bindValue(":good",tag.good?1:0);//bool
query.bindValue(":status", tag.status);//6 chars
query.bindValue(":color", tag.color);//7 chars
query.bindValue(":firstCheckTimestamp", tag.firstCheckTimestamp); //long
query.bindValue(":createdTimestamp", tag.createdTimestamp);//long
query.bindValue(":modifiedTimestamp", tag.modifiedTimestamp);//long
query.bindValue(":fulfilledTimestamp", tag.fulfilledTimestamp);//long
if (query.exec()) {
//qDebug() << "Successfully updated tag database after "<<st.getIntervalCompleteString();
}
else {
qWarning() << "ERROR: could not upsert tag with id " << tag.id<< ". Reason: "<< query.lastError();
}
query.finish();
}
else {
qWarning() << "ERROR: DB not open for upsert tag sqlite3";
}
}
更新:这里是请求的 open():
bool BottleRigStorage::open(){
if(!db.isOpen()){
if(!db.open()){
qWarning() << "ERROR: could not open database. Reason: "<<db.lastError();
}
}
return db.isOpen();
}
只使用一次准备。您的代码正在准备查询
QSqlQuery 创建后的时间。你需要创造
QSqlQuery 在函数外准备,只使用值
绑定和 sql 在函数中查询 exec:
void BottleRigStorage::upsertTag(Tag &tag){
//ScopedTimer st("query time for tag");
if(open()){
query.bindValue(":id", tag.id);//8 chars
query.bindValue(":batchID", tag.batchID);//8 chars
query.bindValue(":retries", tag.retries);//int
query.bindValue(":good",tag.good?1:0);//bool
query.bindValue(":status", tag.status);//6 chars
query.bindValue(":color", tag.color);//7 chars
query.bindValue(":firstCheckTimestamp", tag.firstCheckTimestamp); //long
query.bindValue(":createdTimestamp", tag.createdTimestamp);//long
query.bindValue(":modifiedTimestamp", tag.modifiedTimestamp);//long
query.bindValue(":fulfilledTimestamp", tag.fulfilledTimestamp);//long
if (query.exec()) {
//qDebug() << "Successfully updated tag database after "<<st.getIntervalCompleteString();
}
else {
qWarning() << "ERROR: could not upsert tag with id " << tag.id<< ". Reason: "<< query.lastError();
}
query.finish();
}
else {
qWarning() << "ERROR: DB not open for upsert tag sqlite3";
}
}
这种情况下的查询对象可以是私有成员,例如在数据库初始化之后创建。
您可以通过编译指示调整 sqlite 数据库。例如,下一个代码将增加查询的执行:
m_pDatabase->exec("PRAGMA synchronous = OFF");
m_pDatabase->exec("PRAGMA journal_mode = MEMORY");
有关此的更多信息,您可以阅读 here
当我有 99 个程序时,我遇到了同样的问题,每个程序都有 99 个步骤,我从 Pendrive 中读取 CSV 文件中的数据并将它们插入到数据库中。花了 5 多分钟,但在那之后,我对
做了一些改动
main.cpp
db.open();
db.exec("PRAGMA synchronous = OFF");
db.exec("PRAGMA journal_mode = MEMORY");
并在 class 上添加了数据库提交以用于插入查询
model.cpp
qDebug()<<"can start a transaction PrgQuery:"<<QSqlDatabase::database().transaction();
query.prepare("insert query");
query.exec();
qDebug()<<"end transaction Step Query:"<<QSqlDatabase::database().commit();
这解决了我的问题并将时间减少到 10 秒。像无限力量一样快
在 Qt5.4 中使用 QSqlDatabase 和 sqlite3 在 Ubuntu14 .04 64 位:
首先我在数据库上打开并调用 transaction()
。
接下来我进行 54 个单独的插入查询,每个都准备好,每个都在执行后删除。
最后我打电话给commit()
。
所有调用都完成且没有错误,但执行时间仍然很糟糕(54 次微不足道的插入总共耗时约 500 毫秒)。
我的电脑相当现代,配备了条带化 SSD 磁盘以提高性能。使用 Sqliteman 访问 sqlite 文件时,速度非常快。
那么这是怎么回事?
插入内容如下:
void BottleRigStorage::upsertTag(Tag &tag){
//ScopedTimer st("query time for tag");
if(open()){
QSqlQuery query(db);
query.prepare("INSERT OR REPLACE INTO tags ("
" id"
", batchID"
", retries"
", good"
", status"
", color"
", firstCheckTimestamp"
", createdTimestamp"
", modifiedTimestamp"
", fulfilledTimestamp"
") VALUES ("
" :id"
", :batchID"
", :retries"
", :good"
", :status"
", :color"
", :firstCheckTimestamp"
", :createdTimestamp"
", :modifiedTimestamp"
", :fulfilledTimestamp"
");");
query.bindValue(":id", tag.id);//8 chars
query.bindValue(":batchID", tag.batchID);//8 chars
query.bindValue(":retries", tag.retries);//int
query.bindValue(":good",tag.good?1:0);//bool
query.bindValue(":status", tag.status);//6 chars
query.bindValue(":color", tag.color);//7 chars
query.bindValue(":firstCheckTimestamp", tag.firstCheckTimestamp); //long
query.bindValue(":createdTimestamp", tag.createdTimestamp);//long
query.bindValue(":modifiedTimestamp", tag.modifiedTimestamp);//long
query.bindValue(":fulfilledTimestamp", tag.fulfilledTimestamp);//long
if (query.exec()) {
//qDebug() << "Successfully updated tag database after "<<st.getIntervalCompleteString();
}
else {
qWarning() << "ERROR: could not upsert tag with id " << tag.id<< ". Reason: "<< query.lastError();
}
query.finish();
}
else {
qWarning() << "ERROR: DB not open for upsert tag sqlite3";
}
}
更新:这里是请求的 open():
bool BottleRigStorage::open(){
if(!db.isOpen()){
if(!db.open()){
qWarning() << "ERROR: could not open database. Reason: "<<db.lastError();
}
}
return db.isOpen();
}
只使用一次准备。您的代码正在准备查询 QSqlQuery 创建后的时间。你需要创造 QSqlQuery 在函数外准备,只使用值 绑定和 sql 在函数中查询 exec:
void BottleRigStorage::upsertTag(Tag &tag){ //ScopedTimer st("query time for tag"); if(open()){ query.bindValue(":id", tag.id);//8 chars query.bindValue(":batchID", tag.batchID);//8 chars query.bindValue(":retries", tag.retries);//int query.bindValue(":good",tag.good?1:0);//bool query.bindValue(":status", tag.status);//6 chars query.bindValue(":color", tag.color);//7 chars query.bindValue(":firstCheckTimestamp", tag.firstCheckTimestamp); //long query.bindValue(":createdTimestamp", tag.createdTimestamp);//long query.bindValue(":modifiedTimestamp", tag.modifiedTimestamp);//long query.bindValue(":fulfilledTimestamp", tag.fulfilledTimestamp);//long if (query.exec()) { //qDebug() << "Successfully updated tag database after "<<st.getIntervalCompleteString(); } else { qWarning() << "ERROR: could not upsert tag with id " << tag.id<< ". Reason: "<< query.lastError(); } query.finish(); } else { qWarning() << "ERROR: DB not open for upsert tag sqlite3"; }
}
这种情况下的查询对象可以是私有成员,例如在数据库初始化之后创建。
您可以通过编译指示调整 sqlite 数据库。例如,下一个代码将增加查询的执行:
m_pDatabase->exec("PRAGMA synchronous = OFF"); m_pDatabase->exec("PRAGMA journal_mode = MEMORY");
有关此的更多信息,您可以阅读 here
当我有 99 个程序时,我遇到了同样的问题,每个程序都有 99 个步骤,我从 Pendrive 中读取 CSV 文件中的数据并将它们插入到数据库中。花了 5 多分钟,但在那之后,我对
做了一些改动main.cpp
db.open();
db.exec("PRAGMA synchronous = OFF");
db.exec("PRAGMA journal_mode = MEMORY");
并在 class 上添加了数据库提交以用于插入查询
model.cpp
qDebug()<<"can start a transaction PrgQuery:"<<QSqlDatabase::database().transaction();
query.prepare("insert query");
query.exec();
qDebug()<<"end transaction Step Query:"<<QSqlDatabase::database().commit();
这解决了我的问题并将时间减少到 10 秒。像无限力量一样快