如何取消long-运行 QSqlQuery?
How to cancel long-running QSqlQuery?
如何取消long 运行 QSqlQuery?
数据库正在返回超过 300 万行,并且显示在 QTableView 控件中。我希望能够强制停止两个长时间操作:
- 当数据库是 运行 长时间操作时
- 如果数据库速度很快,但要返回的行数很大,processing/copying/showing 需要很长时间
第2条,不使用QSqlQueryModel可以解决。在这种情况下,手动解析查询结果可以分阶段完成,这将实现,但我也想知道移动数据DB->QTableView的过程是否可以中断和取消。
我试过以下但没有成功:
- QSqlQuery::finish()
- QFuture::取消()
- QSqlDatabase.close() -- 这个会导致应用程序崩溃
如果需要完整的上下文,则为 here。有问题的方法是
on_button_stopQuery_released
在执行期间中止查询(不是获取,这是 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 or grouping 子句。
如何取消long 运行 QSqlQuery?
数据库正在返回超过 300 万行,并且显示在 QTableView 控件中。我希望能够强制停止两个长时间操作:
- 当数据库是 运行 长时间操作时
- 如果数据库速度很快,但要返回的行数很大,processing/copying/showing 需要很长时间
第2条,不使用QSqlQueryModel可以解决。在这种情况下,手动解析查询结果可以分阶段完成,这将实现,但我也想知道移动数据DB->QTableView的过程是否可以中断和取消。
我试过以下但没有成功:
- QSqlQuery::finish()
- QFuture::取消()
- QSqlDatabase.close() -- 这个会导致应用程序崩溃
如果需要完整的上下文,则为 here。有问题的方法是
on_button_stopQuery_released
在执行期间中止查询(不是获取,这是 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 or grouping 子句。