Progress-4GL - 汇总表格的最快方法是什么? (聚合函数:计数、求和等)- OpenEdge 10.2A

Progress-4GL - What is the fastest way to summarize tables? (Aggregate Functions: Count, Sum etc.) - OpenEdge 10.2A

我们正在使用 OpenEdge 10.2A,并使用进度程序生成摘要报告。我们想减少报告的制作时间。

由于使用 Accumulate 和 Accum 函数实际上并不比定义变量来获取汇总值更快,而且它们的可读性更差,所以我们并没有真正使用它们。

我们已经使用 ODBC 连接使用 SQL 命令测试了我们的数据,结果比使用过程快得多。

让我举个例子。我们运行以下程序:

DEFINE VARIABLE i AS INTEGER NO-UNDO.

ETIME(TRUE).
FOR EACH orderline FIELDS(ordernum) NO-LOCK:
    ASSIGN i = i + 1.
END.
MESSAGE "Count = " (i - 1) SKIP "Time = " ETIME VIEW-AS ALERT-BOX.

结果是:

Count= 330805
Time= 1891

当我们运行相当于SQL查询:

SELECT count(ordernum) from pub.orderline

执行时间为141.

简而言之,当我们比较两个结果时; sql 时间比程序时间快 13 倍多。

这只是一个例子。我们可以用其他聚合函数做同样的测试,时间比例变化不大。

我的问题分为两个部分;

1-) 是否可以像使用 sql 查询一样快速地使用过程获取聚合值?

2-) 除了使用实时 SQL 查询之外,还有其他方法可以更快地获取汇总值吗?

手头的问题似乎是"decrease the production time of the reports."。

这引发了一些问题:

  • 现在的报告有多慢?您希望它们多快?
  • 与去年相比,运行宁时间增加了吗?
  • 数据量也增加了吗?
  • 有什么变化吗?服务器、存储、客户端等?

如果没有更多信息,将无法回答您的问题。在以下情况下,从 ABL 访问数据很可能足够快:

  • 您的数据库中设置了正确的索引。
  • 您有 "good" 个查询。
  • 您有足够的系统资源(内存,cpu,磁盘space,磁盘速度)
  • 你有一个数据库 运行 一个不错的设置(-spin,-B 参数等)。

FOR EACH <table> NO-LOCK:SELECT COUNT(something) FROM <somewhere> 这样的简单命令所花费的时间可能并不表示您真正的超级复杂查询可能有多快或多慢 运行。

4gl 和 SQL 引擎使用非常不同的方法将数据发送到客户端。默认情况下 SQL 要快得多。要从 4gl 获得类似的性能,您需要调整几个参数。我建议:

-Mm 32600                  # messages size, default 1024, max 32600
-prefetchDelay             # don't send the first record immediately, instead bundle it
-prefetchFactor 100        # try to fill message 100%
-prefetchNumRecs 10000     # if possible pack up to 10,000 records per message, default 16

在 11.6 之前更改 -Mm 需要同时更改客户端和服务器。从 11.6 开始只需要更改服务器。

-prefetch* 参数至少需要 OpenEdge 10.2b06。

尽管有一些注意事项(除其他事项外,联接不会受益),这些参数可能会极大地提高 "NO-LOCK queries" 的性能。一个简单的:

FOR EACH table NO-LOCK:
  /* ... */
END.

使用上面的参数可以大大提高

使用 FIELDS 列表也有很大帮助,因为它减少了数据量,从而减少了需要发送的消息数量。因此,如果您只需要一些字段而不是整个记录,您可以编写如下代码:

FOR EACH customer FIELDS ( name balance ) NO-LOCK:

或:

FOR EACH customer EXCEPT ( photo ) NO-LOCK:

您已经在使用 FIELDS,并且您的示例查询是一个简单的 NO-LOCK,因此它应该从建议的参数设置中受益匪浅。

一些补充建议:

你的例子可以写成

DEFINE VARIABLE i AS INTEGER NO-UNDO.

ETIME(TRUE).
select count(*) into i from orderline.
MESSAGE "Count = " (i - 1) SKIP "Time = " ETIME VIEW-AS ALERT-BOX.

这应该会产生适度的性能提升。 (这不是使用 ODBC 连接。您可以在普通 4GL 过程中使用 SQL 的子集。如果这可以被认为是好的风格,则值得商榷。)

通过共享内存而不是 TCP/IP 访问数据库应该会显着提高性能,如果您是 运行 服务器上的代码(您这样做)并且您还没有这样做(您没有指定)。

打开查询 q 预选每个 EACH 订单行无锁。 message num-results("q") view-as alert-box.