释义:
我有一个包含 500K 行的表。没有良好索引支持的即席查询需要全表扫描。我想在全表扫描继续时立即查看返回的第一行。然后我想滚动浏览下一个结果。
看来您想要的是某种可以有两个(或更多)线程在工作的系统。一个线程将忙于从数据库同步获取数据,并向程序的其余部分报告其进度。另一个线程将处理显示。
同时,我想显示表扫描的进度,例如:“搜索...到目前为止已找到 500,000 行中的 23 行”。
目前尚不清楚您的查询是否会返回 500,000 行(事实上,我们希望它不会),尽管它可能必须扫描所有 500,000 行(并且到目前为止很可能只找到 23 行匹配)。确定要返回的行数很困难;确定要扫描的行数更容易;确定已扫描的行数非常困难。
如果我滚动得太远,我想显示一条消息,例如:“已到达前瞻缓冲区中的最后一行...查询尚未完成”。
因此,用户已滚动到第 23 行,但查询尚未完成。
这可以做到吗?也许像:spawn/exec、声明滚动光标、打开、获取等?
这里有几个问题。 DBMS(对于大多数数据库来说都是如此,当然对于 IDS 也是如此)在处理一条语句时仍然与当前连接相关。获得有关查询进展情况的反馈很困难。您可以查看查询启动时返回的估计行数(SQLCA 结构中的信息),但这些值很可能是错误的。当您到达 23 行中的第 200 行时,您必须决定要做什么,否则您只能到达 5,697 行中的第 23 行。有总比没有好,但并不可靠。确定查询进展到什么程度是非常困难的。并且有些查询需要实际的排序操作,这意味着很难预测需要多长时间,因为在排序完成之前没有可用的数据(并且一旦排序完成,只有之间进行通信所花费的时间) DBMS 和应用程序来阻止数据的传输)。
Informix 4GL 有很多优点,但线程支持并不是其中之一。该语言的设计并未考虑到线程安全,并且没有简单的方法可以将其改进到产品中。
我确实认为您所寻求的最容易由两个线程支持。在像 I4GL 程序这样的单线程程序中,在等待用户输入更多输入(例如“向下滚动下一个充满数据的页面”)时,没有一种简单的方法来获取行。
FIRST ROWS优化是对DBMS的一个提示;它可能会或可能不会给感知性能带来显着的好处。总的来说,这通常意味着从 DBMS 的角度来看,查询的处理不太理想,但快速向用户提供结果可能比 DBMS 上的工作负载更重要。
在下面某个被严重否决的答案中,弗兰克喊道(但请不要喊):
这正是我想要做的,生成一个新进程来开始显示first_rows并滚动它们,即使查询尚未完成。
好的。这里的困难是在两个客户端进程之间组织 IPC。如果两者都连接到 DBMS,则它们具有单独的连接,因此一个会话的临时表和游标对另一个会话不可用。
执行查询时,会创建一个临时表来保存当前列表的查询结果。 IDS 引擎是否会在此临时表上放置独占锁,直到查询完成?
并非所有查询都会生成临时表,尽管滚动游标的结果集通常确实具有与临时表大致相同的内容。 IDS 不需要在支持滚动游标的临时表上放置锁,因为只有 IDS 才能访问该表。如果它是常规临时表,则仍然不需要锁定它,因为除了创建它的会话之外,无法访问它。
我所说的 500k 行是指查询表中的 nrows,而不是返回多少预期结果。
也许更准确的状态消息是:
Searching 500,000 rows...found 23 matching rows so far
我知道可以在 sysmaster:sysactptnhdr.nrows 中获得准确的 nrows 计数?
大概;您还可以使用“SELECT COUNT(*) FROM TheTable”获得快速准确的计数;这不会扫描任何内容,而只是访问控制数据 - 可能实际上与 SMI 表 sysmaster:sysactptnhdr 的 nrows 列中的数据相同。
因此,催生新流程显然并不是成功的秘诀。您必须将查询结果从生成的进程传输到原始进程。正如我所说,具有单独显示和数据库访问线程的多线程解决方案可以以某种方式工作,但使用 I4GL 执行此操作存在问题,因为它不支持线程。您仍然需要决定客户端代码如何存储用于显示的信息。