qt - 为什么我的 sqlite 查询在 Qt5 中这么慢?

标签 qt sqlite qt5 qtsql qsqldatabase

Qt5.4中,在Ubuntu14.04 64位上使用QSqlDatabasesqlite3:

首先,我打开数据库并调用 transaction()

接下来,我进行 54 个单独的插入查询,每个查询都已准备好,每个查询在执行后都被删除。

最后我调用commit()

所有调用都完成且没有错误,但执行时间仍然很糟糕(54 次简单插入总共大约需要 500 毫秒)。

我的计算机相当现代,并且具有 strip 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();
}

最佳答案

  1. 仅使用一次准备。您的代码正在准备每个查询 QSqlQuery 创建后的时间。你需要创建 QSqlQuery 在函数之外准备,并且只是使用值 函数中的绑定(bind)和sql查询执行:

    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";
    }
    

    }

    这种情况下的查询对象可以是私有(private)成员,并且可以在例如数据库初始化之后创建。

  2. 您可以通过编译指示调整 SQLite 数据库。例如,下一个代码将增加查询的执行:

    m_pDatabase->exec("PRAGMA 同步 = OFF"); m_pDatabase->exec("PRAGMA Journal_mode = MEMORY");

    有关此内容的更多信息,您可以阅读 here

关于qt - 为什么我的 sqlite 查询在 Qt5 中这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31197144/

相关文章:

sqlite - 为设备选择嵌入式Linux

c++ - 在 qt 中解析嵌套 json 的意外结果(数组不存在)

c++ - 如何用Qt5编译QwtPlot3d?

mysql - 如何使用QT在MYSQL数据库中存储文本文件?

c++ - 没有参数但仍然进行计算的函数如何使用gtest?

c++ - Qt - 在 TableView 中自动组合框?

java - 用于插入到 sql : event handler is not in the Namespace or there is an error in the script 的按钮

ruby-on-rails - 从旧源测试 Gem

java - 添加到数据库时出现空指针异常

c++ - Qt5 中的 GStreamer 错误