Qt массовая вставка sqlite - PullRequest
0 голосов
/ 19 сентября 2019

Для проекта qt / qml я делаю вставки в базу данных.Поскольку есть много данных для отправки (200+ вставок / сек), я хочу сделать это навалом.Вставки находятся в разных таблицах.У меня есть вопросы уже подготовлены.Я сделал один метод, который должен фиксировать запросы после того, как он достиг 100 запросов.

//in the constructor i laready say mdb.transaction() for the first run.
bool DatabaseWriter::executeQuery(QString insertQuery)
{
   queryCounter ++;
   qDebug() << QString::number(queryCounter);
   QSqlQuery query(mydb);

    if(!query.exec(insertQuery))
    {
        qDebug("%s.", qPrintable(mydb.lastError().text()));
        qDebug() << "Something went wrong while running " + insertQuery + " from the database";
        return false;
    }
    if(queryCounter > 100)
    {
         qDebug() <<  "Should commit";
        if(!mydb.commit())
        {
            qDebug() <<  "commit failed";
        }
        mydb.transaction();
        queryCounter = 0;
    }

    return true;
}

Но mydb.commit () возвращает false.Как правильно выполнить массовую вставку?

Я также попытался:

if(query != ""){

    query_to_commit += query +";";
    insert_counter ++;
    if(insert_counter > 100)
    {
         dbWriter.executeQuery("BEGIN TRANSACTION; "+query_to_commit+ " COMMIT;");
         insert_counter = 0;
         query_to_commit = "";
         CustomLogger::log("Running bulk insert");
    }
}

, которая генерирует массовую транзакцию, которая прекрасно работает при выполнении ее в моем файле базы данных sqlite, но не когда я это делаюэто с моим кодом, в моем коде я получаю: Driver not loaded Driver not loaded. Я не получаю эту ошибку при выполнении одного запроса на вставку.

Для простоты, как я могу запустить, например:

INSERT  INTO settings (name, x, y) VALUES('somename', 100, 20)
INSERT  INTO different_table(bla, x, y) VALUES('bla', 100, 20)

Один раз вместо двух.Или Как я могу выполнить:

BEGIN TRANSACTION;
INSERT  INTO settings (name, x, y) VALUES('somename', 100, 20)
INSERT  INTO different_table(bla, x, y) VALUES('bla', 100, 20)
COMMIT;

Основная цель - не писать 200 раз в секунду, а просто делать это за один раз, если я делаю это 200 раз в секунду, мой графический интерфейс блокируется / глючит (включенту же ветку я догадываюсь).

1 Ответ

1 голос
/ 24 сентября 2019

Я сделал отдельный запрос thead, мой заголовочный файл:

#ifndef QUERYTHREAD_H
#define QUERYTHREAD_H
#include <QThreadPool>
#include <QString>
#include <QSqlQuery>
#include <QSqlDatabase>

class QueryThread : public QRunnable
{
    QString query_to_run;
    static int queryNumber;

public:
    QueryThread(QString query_list);
    void run();
};


#endif // QUERYTHREAD_H

мой файл cpp:

#include "querythread.h"
#include <QDebug>
#include <windows.h> // for Sleep
#include <QSqlError>
#include "customlogger.h"
#include "databasewriter.h"

int QueryThread::queryNumber = 1;

QueryThread::QueryThread(QString query)
{
    this->query_to_run = query;
}

void QueryThread::run()
{

    {
        // Make sure to have a unique database connection name by using the a static counter.
        QString connectionName = "connection_name_"+QString::number(queryNumber ++);
        QSqlDatabase mydb = QSqlDatabase::addDatabase("QSQLITE", connectionName);
        mydb.setDatabaseName(DatabaseWriter::dirPath);

        if(!mydb.open()){
            CustomLogger::log("Cant open DB");
            return;
        }
        QSqlQuery query(mydb);
        if(!query.exec(query_to_run))
        {
            CustomLogger::log(qPrintable(mydb.lastError().text()));
            CustomLogger::log("Something went wrong while running query: " + query_to_run);
        }
        mydb.close();
    }
    QSqlDatabase::removeDatabase("QSQLITE");
}

Я начинаю новый запрос с:

QueryThread *queryThread = new QueryThread(insertQuery);
// QThreadPool takes ownership and deletes 'queryThread' automatically
QThreadPool::globalInstance()->start(queryThread);

Эта реализация запускает запросы в отдельном потоке пользовательского интерфейса.Он открывает соединение для каждой вставки, поэтому я не уверен, что это решение не вызывает проблем с производительностью.до сих пор это выглядит хорошо с 1.600.000 вставок за 16 часов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...