0

如何取消长时间运行的 QSqlQuery?

数据库返回 3M+ 行,并显示在 QTableView 控件中。我希望能够强制停止两个长时间的操作:

  1. 当数据库运行长时间操作时
  2. 如果数据库速度很快,但是要返回大量行并且处理/复制/显示这些行需要很多时间

第二个项目符号,可以通过不使用 QSqlQueryModel 来解决。在这种情况下,可以分阶段手动解析查询结果并实现,但我也想知道移动数据DB->QTableView的过程是否可以中断和取消。

我试过以下但没有成功:

  • QSqlQuery::finish()
  • QFuture::cancel()
  • QSqlDatabase.close() - 这一个崩溃应用程序

如果需要完整的上下文,它就在这里。有问题的方法是

on_button_stopQuery_released
4

1 回答 1

2

在执行期间中止查询(不是获取,这是 QSqlQuery::finish 所做的)在所有数据库中都是偶然的。Qt 本身不支持这一点;解决方法将是特定于后端的。

例如,使用 PostgreSQL,您可以执行以下操作:

  • 在您的原始连接中,检索连接 ID ( SELECT pg_backend_pid();) 并保存
  • 当您想中止查询时,请打开第二个连接并通过发出终止查询SELECT pg_cancel_backend(saved_id);

SQLite 有sqlite3_interrupt(sqlite3*). 这会中断查询并且不会关闭连接。

MySQL 类似于 PostgreSQL:

  • 首先检索连接 ID ( SELECT CONNECTION_ID();)
  • 然后通过另一个连接 ( KILL [CONNECTION|QUERY] $connection_id) 将其杀死。

如您所见,即使提供的功能也是特定于后端的。Postgres 只能中止连接,而 SQLite 只能中止查询。因此,实现这一点的最简单方法是在查询被中止并且连接仍然有效时丢弃连接。然后你可以有一个简单的两个API接口进行取消管理(伪代码,即Python):

class IConnectionCancellation:
    def register(connection):
        # save/retrieve connection ID

    def cancel():
        # open second connection, send backend-specific query

对于大型结果集,请考虑在您的模型中使用canFetchMore和。fetchMore这样您就不必在向用户显示某些结果之前处理整个结果集;使用起来可能会更顺畅。当然,由于例如 order by 或 grouping 子句,对固有的查询执行延迟没有帮助。

于 2018-08-11T20:33:48.537 回答