【QT性能优化】QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化
QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化
简介
本文介绍了QT模型视图代理框架中的QT表格控件和QT数据库模块中的QT数据库查询模型结合使用的一个应用实践案例:QT高性能表格控件分页展示千万行数据。本文介绍了这个应用实践案例的运行效果和源代码。这个应用实践案例实测运行表明,QT表格控件具备在3毫秒之内快速从1000万数据记录的SQLite数据库的一个数据表中查询读取10000记录的能力。 本文还介绍了QT表格控件和QT数据库模块的一些总体情况。本文最后通过QT框架的源代码调试运行分析了QT表格控件的性能为什么如此之高。
正文
QT高性能表格控件分页展示百万行数据运行效果展示
系统配置
硬件配置: SSD。
操作系统: Windows。
数据库系统:SQLite数据库。
QT版本: QT。
1000万条记录的数据表中一次读取1万条记录
实测结果:1000万条记录的数据表中一次读取1万条记录,首次查询耗时小于3毫秒(ms=千分之一秒),后续查询耗时小于1毫秒。采用整数主键查询,主键在数据表中的位置对查询性能没有显著影响。
QT高性能表格控件1000万条记录的数据表中展示1万条记录
QT表格控件+QT数据库模块:1000万条记录的数据表中一次读取1万条记录
1000万条记录的数据表中一次读取10万条记录
实测结果:1000万条记录的数据表中一次读取10万条记录,首次查询耗时小于3毫秒(ms=千分之一秒),后续查询耗时小于1毫秒。
QT高性能表格控件1000万条记录的数据表中展示10万条记录
QT表格控件+QT数据库模块:1000万条记录的数据表中一次展示10万条记录
1000万条记录的数据表中一次读取100万条记录
实测结果:1000万条记录的数据表中一次读取100万条记录,首次查询耗时小于3毫秒(ms=千分之一秒),后续查询耗时小于1毫秒。
QT高性能表格控件1000万条记录的数据表中展示100万条记录
QT表格控件+QT数据库模块:1000万条记录的数据表中一次读取100万条记录
使用QT 模型视图代理框架实现1000完条记录的数据表中读取1000条记录的运行效果的视频参考如下:
视频: QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化效果
QT能否撑得起千万级数据表这样的规模?看完补天云这个实测视频就有答案了! QT性能优化之QT6框架高性能模型视图代理框架千万级数据表分页查询优化
QT高性能表格控件分页展示百万行数据应用程序源代码
为了减少本文的篇幅,在此只列举了一部分关键代码。
QT初始化数据表代码:1000万条记录
几个有关的常量。
QT高性能表格控件性能测试程序用到的常数
QT高性能表格控件性能测试程序
数据库初始化代码:
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT主界面代码
以下是主窗口也就是QT表格控件所在窗口的构造函数。
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT高性能表格控件性能测试程序
QT表格控件
QT图形视图框架整体介绍
下图是QT助手API DOC中介绍的QT Model-View-Delegate(模型视图代理)框架的整体结构。
QT模型视图代理框架整体结构
图中Model就是模型,View是视图,Delegate是代理。三者之间的关系看图已经很清楚了。其中,View用于用户界面交互,包括数据展示的总体框架等;Model用于向View提供数据支持,包括查询数据和保存数据(修改和插入);Delegate用于具体展示数据和具体提供数据编辑功能的用户交互界面。
QT表格控件
QT模型视图代理框架中提供了很多视图类型,本文介绍的QT表格控件QTableView就是一种视图类型。这个类型提供了表格类型的界面常用的各种功能,包括对横向表头和纵向表头以及单元格的控制和修饰。
QT表格控件界面美化效果演示
QT表格窗口
QT还提供了另外一种视图类型:QTableWidget类型,这个类型是QTableView类型的派生类型, 在QTableView的基础上做了更多粗粒度的封装的API接口,使得QTableWidget使用起来更加人性化,也就是符合大多数软件工程师的常规思维;当然QTableWidget也屏蔽了一些QTableView的底层细节API 接口,也就是有一些QTableView的一些API在QTableWidget中被使用C++的一些基础语法进行了屏蔽。
QT数据库组件
QT数据库模块整体介绍
QT助手API DOC中介绍了QT数据库模块的整体情况。
QT数据库模块整体结构
QT数据库模块包含了用户界面层(UI Layer)、SQL接口层(SQL API Layer),和驱动程序层(Driver Layer)。
在QT应用程序中使用QT数据库模块,必须在项目文件中做如下配置。
对于CMake编译构建管理工具:
QT数据库模块CMake编译构建管理项目配置
对于qmake编译构建管理工具:
QT数据库模块qmake编译构建管理项目配置
用户界面层(UI Layer)
这里的UI可以理解成是数据库模块的普通应用开发者的API 接口;按照QT模型视图代理框架的概念体系,这个UI也可以理解成是这些类型可能会放在用户界面相关的程序代码中去用,比如在与视图有关的代码中去调用这些API。
比如QSqlQueryModel经常作为模型类型在模型视图代理框架中使用,当然也可以独立使用。
SQL接口层(SQL API Layer)
QT数据库模块使用QSqlDatabase类型提供通用的数据库的连接和SQL查询操作的API接口。
驱动程序层(Driver Layer)
QT数据库模块使用QSqlDriver类型定义了一些数据库的一些抽象的底层操作。特定数据库相关的具体实现有特定数据库对应的派生类提供。
QT 助手API DOC中描述了QT框架对特定数据库的支持情况如下图所示:
QT数据库模块驱动程序层
QT表格控件的性能何以如此之高?
查询和遍历不是同一个概念
下面是在进行SQLite数据库查询之后,对10000条记录进行逐条记录遍历的代码。
QT数据库模块查询遍历实例代码
经实测运行上述代码,遍历10000条记录耗时约30毫秒。
既然仅仅遍历10000条记录就耗时30毫秒,那么QT表格控件是如何做到只花了3毫秒就完成了数据库查询操作呢?
推测可能原因是QSqlQueryModel中并没有直接的完整遍历查询结果中的10000条记录,而是QTableView控件中只遍历了少量的数据记录。当用户拖动滚动条时,QTableView控件再根据实际需求请求QSqlQueryModel去遍历更多相应的数据记录。因此看起来就像是QT表格控件在小于1毫秒的时间之内就查询到了10000条记录,甚至100万条记录。
对预取数据的支持
本文作者经过调试QT源代码后发现了如下源代码:
QT模型视图代理框架对数据预取的支持
这里定义了QAbstractItemView类型的数据记录的预取功能。每次当表格控件QTableView的界面发生变化时,就可能触发数据记录预取函数prefetch()的调用执行,这个函数每次预取255条数据记录。也就是说尽管执行SQL语句时从SQLite数据库中查询到了10000条记录,甚至100万条记录,但是QTableView每次只从查询结果中取出255条记录。这样搞当然极大的提升了包括QTableView在内的所有基于QAbstractItemView类型的视图控件的性能。
还有更多数据记录吗?
现在已经知道了QAbstractItemView每次只遍历255条数据记录,而QSqlQueryModel中的查询结果记录集中可能有10000条数据记录,甚至100万条数据记录。因此模型自己必须知道查询结果记录集中是否还有更多数据记录可以提供给QAbstractItemView视图,当然实际上是提供给这个类型的派生类QTableView之类的视图。
模型类的祖宗类QAbstractItemModel设计了两个跟数据预取有关的虚函数。
QT模型视图代理框架中模型类与数据预取有关的虚函数
当然,包括QSqlQueryModel在内的各种具体模型类都实现了这两个虚函数,以此成为一个支持数据预取(prefetch)的模型类。canFetchMore()的作用是判断是否还能获取到更多的数据记录,如果是则返回TRUE否则返回FALSE。fetchMore()的作用是具体获取到更多的数据。
在这次调试实测过程中,创建了一个QSqlQueryModel的派生类ButianyunSqlQueryModel,用于观测何时调用这两个数据预取函数。
ButianyunSqlQueryModel实现了数据预取虚函数
下面是调试过程中看到的函数调用栈。
QT模型视图代理框架中对数据预取函数的调用栈
至此对与本文主题相关的表格控件的调试分析工作已经完成。
总结
本文先通过一个具体应用实例(QT高性能表格控件分页展示百万行数据)展示了从1000万条SQLite数据记录中查询10000条记录并快速显示在QT表格控件的实际运行效果,同时给出了这个实例的一些源代码。然后介绍了QT表格控件QTableView和QT数据库组件的一些类型。后面又通过QT源码调试分析了为什么QT表格控件的性能如此之高的底层逻辑。
推荐QT性能优化技术博客专栏:
QT性能优化
如果您认为这篇文章对您有所帮助,请您一定立即点赞+喜欢+收藏,本文作者将能从您的点赞+喜欢+收藏中获取到创作新的好文章的动力。如果您认为作者写的文章还有一些参考价值,您也可以关注这篇文章的作者。