2

In Qt5.4 using QSqlDatabase with sqlite3 on Ubuntu14.04 64bit:

First I open and call transaction() on the db.

Next I make 54 individual insert queries, each prepared, each deleted after execution.

Finally I call commit().

All calls complete without error and still the execution time is horrible (around 500 ms total for 54 trivial inserts).

My computer is reasonably modern and has striped SSD disks for performance. When accessing the sqlite file using Sqliteman it is blazingly fast.

So what is going on?

Here is the insert:

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

UPDATE: And here is open() as requested:

bool BottleRigStorage::open(){
    if(!db.isOpen()){
        if(!db.open()){
            qWarning() << "ERROR: could not open database. Reason: "<<db.lastError();
        }
    }
    return db.isOpen();
}
4

2 回答 2

5
  1. 只使用一次准备。每次创建 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";
    }
    

    }

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

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

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

    有关此的更多信息,您可以在此处阅读

于 2015-07-03T13:39:13.543 回答
2

当我有 99 个程序并且每个程序都有 99 个步骤时,我也面临同样的问题,我正在从 CSV 文件中读取 Pendrive 中的数据并将它们插入数据库。它花了超过 5 分钟,但在那之后,我在

主文件

   db.open();
   db.exec("PRAGMA synchronous = OFF");
   db.exec("PRAGMA journal_mode = MEMORY");

并在类上添加了 db commit 以进行插入查询

模型.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 秒。非常快,就像无限的力量

于 2018-05-30T11:26:35.943 回答