具有较大记录的表会经常在每个循环中命中导致性能问题吗? - 进度 4GL

问题描述 投票:0回答:1

我有一个以下简单的查询,它会导致性能问题。表 xxdata 有大量记录,并且根据表 xxfin 中可用的总记录,它经常获得点击。(即表 xxfin 中有 1000 条可用记录,然后点击表 xxdata 1000 次)。

这会导致性能问题。根据此查询的检查 XREF,编译器显示两个表的正确索引。

FOR EACH xxfin NO-LOCK WHERE xxfin.setValue = 9:
**Some additional logic goes here but this is not causing any issues, Since I have commented them and checked**
    FOR EACH xxdata NO-LOCK 
       WHERE xxdata.linkno = xxfin.setValue
       AND xxdata.duo = "FINISHED":
    END. /*FOR EACH xxdata*/
END. /*FOR EACH xxfin */
openedge progress-4gl
1个回答
0
投票

OpenEdge 查询效率和性能取决于所选索引的质量以及客户端正在处理的数据量。

在您的示例中,如果 xxfin.setValue 是索引的主要组成部分,那么,因为您有一个简单的“相等匹配”,所以代码块的该部分正在选择 xxfin 记录的最小数量。

但是 - 如果 xxfin.setValue 不是索引的主要组成部分,您将处理“整个索引”表扫描。 IOW,您将检查表中的每条记录以查看 setValue 是否 = 9。

(您可以使用 XREF 选项编译代码,并在输出中查找 SEARCH 以查看选择了哪个索引,即使正在使用索引时,短语 WHOLE-INDEX 也意味着正在进行表扫描。)

同样,如果 xxdata.linkno 和 xxdata.duo 是主要组件(无论顺序),那么您的第二个查询应该非常高效。

但是 - 如图所示,您的外循环似乎是不必要的。在我看来,你可以将其重写为:

for each xxdata no-lock
  where xxdata.linkno = 9 
    and xxdata.duo = "finished":

  /* do stuff */

end.

消除外部循环将(可能)允许“消息”包含更多数据(这受到 -Mm、-prefetchNumRecs 和 -prefetchFactor 启动参数的影响;“越大越好”)。将更多数据打包到每条消息中并避免在外循环无意义地迭代时不必要地拆分消息将有所帮助。

如果您正在做的事情未在 xxfin 记录中显示,您仍然可以这样做。只需重构 xxdata 循环内发生的事情即可。也许是这样的:

for each xxdata no-lock
  where xxdata.linkno = 9 
    and xxdata.duo = "finished":

  find xxfin no-lock where xxfin.setvalue = xxdata.linkno.

  /* do stuff */

end.

当然,逻辑将取决于您在外循环中所做的事情(如果有的话)(您尚未显示),但可能有一种方法可以将其移动到内部。

您可以做的另一件事是,如果连接类型是远程连接(您在客户端启动参数中使用了 -S),则使用 FIELDS 列表。

例如:

for each xxdata fields( linkno duo )no-lock
  where xxdata.linkno = 9 
    and xxdata.duo = "finished":

  /* do stuff */

end.

真实代码需要列出“do stuff”注释所在位置实际引用的字段。

这将减少传输数据的大小,从而获得更好的性能。在远程连接场景中,改进可能是巨大的。

© www.soinside.com 2019 - 2024. All rights reserved.