目录一、前言二、功能特点2.1 软件模块2.2 基础功能2.3 特色功能三、体验地址四、效果图五、相关代码一、前言 随着时间的增加,存储的历史记录也在不断增加,如果设备数量很多,存储
随着时间的增加,存储的历史记录也在不断增加,如果设备数量很多,存储间隔很短,不用多久,数据库中的记录就非常多,至少是百万级别起步,而且有些用户还是需要存储每一次的采集的数据,这数据量别说一年,就是一个月下来都是恐怖级别的,所以这就涉及到一个重要的需求,如何自动清理早期的不需要的数据,比如只保存最近10万条记录,或者保存最近30天的记录,这就需要安排个线程,在线程中打开数据库以后,每隔一段时间去查询记录数量,超过了设定的最大值,则按照时间顺序把早期的数据删除,其实就是执行一个sql语句。如果设置的是只存储最近30天的记录,则每隔一段时间执行删除sql语句,带上条件where 时间<(今天-30)。由于是在线程中打开的数据库,所以在线程中执行的sql语句都不会对主界面使用的数据库相关处理造成卡顿。
光有数据记录清理可能还是不够的,比如系统还不断的在存储报警图片或者其他数据文件,由于硬盘的大小有限,也需要一个机制做清理,尤其是对于视频监控系统尤为重要。由于和数据库记录清理功能类似,而且数据库清理线程99.99%的时间都是空余的,就算是到了需要清理的时候,也是一次性清理多条,也不会频繁的在清理中,为了不让这个线程闲着,直接也把清理文件的机制也放到了这个类,指定要监听的目录,指定最大的大小,每隔一段时间读取下大小,超过了则清理早期的文件。
设备监控模块,包括数据监控(表格形式展示)、设备面板(面板形式展示)、地图监控(地图形式展示)、曲线监控(曲线形式展示)。
数据查询模块,包括报警记录、运行记录、操作记录。
系统设置模块,包括基本设置、端口管理、控制器管理、探测器管理、报警联动、类型设置等。
其他设置模块,包括用户管理、地图管理、位置调整、组态设计、设备调试等。
国内站点:https://gitee.com/feiyangqingyun
国际站点:Https://GitHub.com/feiyangqingyun
体验地址:https://pan.baidu.com/s/1foas7ytSXh7gHOTDqDREjQ 提取码:axip 文件名:bin_iotsystem.zip。
int DbCleanThread::getCount()
{
int count = -1;
if (!dbOk) {
return count;
}
time.restart();
QString sql = QString("select count(%1) from %2").arg(countName).arg(tableName);
QSqlQuery query(database);
if (query.exec(sql)) {
if (query.next()) {
count = query.value(0).toInt();
QString msg = QString("(共 %1 条/用时 %2 秒)").arg(count).arg(getUseTime());
emit debug(QString("%1数据库获取记录行数%2").arg(dbFlag).arg(msg));
emit receiveCount(tableName, count, time.elapsed());
}
}
return count;
}
QStringList DbCleanThread::getCleanValue(int cleanCount)
{
QStringList list;
if (!dbOk) {
return list;
}
QSqlQuery query(database);
query.setForwardOnly(true);
QString sql = DbHelper::getSelectCountSql(dbType, tableName, whereColumnName, "", orderSql, cleanCount);
if (query.exec(sql)) {
while (query.next()) {
list << query.value(0).toString();
}
}
return list;
}
void DbCleanThread::cleanData()
{
if (!dbOk) {
return;
}
//首先查找总记录数,如果总记录数超过限制,则将超出的部分按照字段排序进行删除
int count = getCount();
int cleanCount = (count - maxCount);
if (cleanCount < 100) {
return;
}
time.restart();
//每次最大清理1000条数据
cleanCount = cleanCount > 1000 ? 1000 : cleanCount;
//将要删除的数据指定字段集合查询出来
QStringList list = getCleanValue(cleanCount);
if (list.count() == 0) {
return;
}
//删除数据
QSqlQuery query(database);
QString sql = QString("delete from %1 where %2 in(%3)").arg(tableName).arg(whereColumnName).arg(list.join(","));
dbOk = query.exec(sql);
//qDebug() << TIMEMS << sql;
QString msg = QString("(共 %1 条/用时 %2 秒)").arg(cleanCount).arg(getUseTime());
if (dbOk) {
emit debug(QString("%1数据库清理数据成功%2").arg(dbFlag).arg(msg));
} else {
QString text = database.lastError().text();
emit error(QString("%1数据库清理数据失败%2, 原因: %3").arg(dbFlag).arg(msg).arg(text));
qDebug() << TIMEMS << this->objectName() << text;
}
}
void DbCleanThread::cleanPath()
{
if (dirPath.isEmpty()) {
return;
}
//找出该文件夹下的所有文件夹
QDir dir(dirPath);
if (!dir.exists()) {
return;
}
//按照目录查找,过滤文件夹,按照文件名称排序
dir.setFilter(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
dir.setSorting(QDir::Name);
QStringList list = dir.entryList();
//遍历所有目录,对所有文件大小相加得到总大小,文件就在文件夹下,不会再有子目录
qint64 size = 0;
foreach (QString path, list) {
QDir d(dirPath + "/" + path);
QFileInfoList infos = d.entryInfoList(dirFileFilter);
foreach (QFileInfo info, infos) {
size += info.size();
}
//转化成MB,超过预定大小自动删除第一个文件夹,跳出循环无需继续判断
int sizeMB = size / (1024 * 1024);
if (sizeMB >= dirMaxSize) {
//删除该目录下的所有文件
QString path = dirPath + "/" + list.at(0);
QDir dir(path);
dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
QStringList files = dir.entryList();
foreach (QString file, files) {
dir.remove(file);
qDebug() << TIMEMS << "删除文件" << path << file;
}
//删除文件夹本身
dir.rmdir(path);
QString msg = QString("(共 %1 个文件/用时 %2 秒)").arg(files.count()).arg(getUseTime());
emit debug(QString("%1数据库自动清理目录成功%2").arg(dbFlag).arg(msg));
break;
}
}
}
void DbCleanThread::deletePath(const QString &path)
{
QDir dir(path);
#if (Qt_VERSION >= QT_VERSION_CHECK(5,0,0))
//这个方法可以递归彻底删除文件夹 不管文件夹下是否有文件 比较暴力
//此方法慎用 必须指定明确的文件夹 不然删除默认的目录哭都来不及 网上多个人中招
dir.removeRecursively();
#else
//循环遍历删除文件及文件夹
dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
QFileInfoList fileList = dir.entryInfoList();
foreach (QFileInfo fi, fileList) {
if (fi.isFile()) {
fi.dir().remove(fi.fileName());
} else {
deletePath(fi.absoluteFilePath());
dir.rmpath(fi.absoluteFilePath());
}
}
//最后删除最外层的目录
dir.rmpath(path);
#endif
}
以上就是Qt物联网管理平台之实现自动清理早期数据功能的详细内容,更多关于Qt自动清理数据的资料请关注编程网其它相关文章!
--结束END--
本文标题: Qt物联网管理平台之实现自动清理早期数据功能
本文链接: https://lsjlt.com/news/154124.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0