sqlite - qt批量插入sqlite
问题描述
对于 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 次,我的 gui 会被阻塞/错误(我猜是在同一个线程上)。
解决方案
我做了一个单独的查询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);
此实现在 ui 线程的单独线程上运行查询。它为每个插入打开一个连接,所以我不确定这个解决方案是否不会导致性能问题。到目前为止,在 16 小时内插入 1.600.000 次看起来还不错。
如果您进行大量插入操作,则可以将数据库置于wal 模式以避免数据库被锁定。
推荐阅读
- reactjs - clearInteval 不能与 ReactJS 一起工作
- java - HTTPUrlConnection 为 Linux 返回 400 但在 Windows 上工作
- android - 在 AsyncTask 上尝试使用 SQLite 检索数据的奇怪行为
- javascript - 最初加载 webpack 时查询的数据消失,然后当我转到网站上的其他页面并返回时出现
- label - Jena:推理规则的标签定义错误
- laravel - 试图获取非对象的属性“image_url”(查看:/app/resources/views/library.blade.php)
- mongodb - 使用 mongoose 在 mongodb 集合中添加带有字符串的电子邮件地址
- r - 重新排列 R 中热图的数据框
- youtube - 为什么我的 YouTube 订阅按钮变暗且无法点击?
- laravel - 在 PDF 上导出希腊字符显示为框