运行 一个循环所用的时间(Progress 4GL)
Time taken to run a loop (Progress 4GL)
我写了一个查询,其中包含多个 for each 语句。查询需要 20 多分钟来获取数据。有没有办法检查每个循环开始和结束的时间。 (每个循环执行需要多少时间以及完成程序所需的总时间)。
使用ETIME
您可以启动毫秒计数器。它可以被调用一次或多次以告知自重置以来已经过去了多长时间。
ETIME(TRUE).
/*
Loop is here but instead I'll insert a small pause.
*/
PAUSE 0.5.
MESSAGE "This took" ETIME "milliseconds" VIEW-AS ALERT-BOX.
处理几分钟时,毫秒可能没有用。然后你可以使用 TIME
来跟踪秒数,但你需要自己处理开始时间。
DEFINE VARIABLE iStart AS INTEGER NO-UNDO.
iStart = TIME.
/*
Loop is here but instead I'll insert a slightly longer pause.
*/
PAUSE 2.
MESSAGE "This took" TIME - iStart "seconds" VIEW-AS ALERT-BOX.
如果您想跟踪多次,那么输出到日志文件可能更好,而不是使用 MESSAGE-box,它将停止执行直到被点击。
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE STREAM str.
OUTPUT STREAM str TO c:\temp\timing.txt.
ETIME(TRUE).
/*
Fake loop
*/
DO i = 1 TO 20:
PAUSE 0.1.
PUT STREAM str UNFORMATTED "Timing no " i " " ETIME "ms" SKIP.
END.
OUTPUT CLOSE.
您可以按照您的要求进行操作(只需遵循 JensD 的建议),但使用分析器可能会更好。您可以轻松地为代码片段添加分析:
assign
profiler:enabled = yes
profiler:description = "description of this test"
profiler:profiling = yes
profiler:file-name = "filename.prf"
.
/* this is deliberately awful code that should take a long time to run */
for each orderline no-lock:
for each order no-lock:
for each customer no-lock:
if customer.custNum = order.custNum and orderLine.orderNum = orderLine.orderNum then
. /* do something */
end.
end.
end.
/* end of test snippet */
assign
profiler:enabled = no
profiler:profiling = no
.
profiler:write-data().
然后您可以将该 prf 文件加载到分析工具中。具体细节取决于您的开发环境——如果您使用的是最新版本的 PSDOE,则包含一个 Profiler 分析器,如果没有,您可能需要下载 ProTop
https://demo.wss.com/download.php 并使用 lib/zprof_topx.p.
中包含的简单报告
最终您会发现,您的一个或多个 FOR EACH 语句几乎肯定使用了与可用索引不匹配的 WHERE 子句。
要解决此问题,您需要确定实际选择了哪些索引并查看索引选择规则。可以在此处找到关于该主题的一些优秀 material:http://pugchallenge.org/downloads2019/303_FindingData.pdf
如果您不想费心阅读那篇文章,那么您至少应该看一下实际的索引选择,如下所示:
compile program.p xref program.xref
所选指数是否符合您的预期? WHOLE-INDEX(又名 "table scan")出现了吗?
我写了一个查询,其中包含多个 for each 语句。查询需要 20 多分钟来获取数据。有没有办法检查每个循环开始和结束的时间。 (每个循环执行需要多少时间以及完成程序所需的总时间)。
使用ETIME
您可以启动毫秒计数器。它可以被调用一次或多次以告知自重置以来已经过去了多长时间。
ETIME(TRUE).
/*
Loop is here but instead I'll insert a small pause.
*/
PAUSE 0.5.
MESSAGE "This took" ETIME "milliseconds" VIEW-AS ALERT-BOX.
处理几分钟时,毫秒可能没有用。然后你可以使用 TIME
来跟踪秒数,但你需要自己处理开始时间。
DEFINE VARIABLE iStart AS INTEGER NO-UNDO.
iStart = TIME.
/*
Loop is here but instead I'll insert a slightly longer pause.
*/
PAUSE 2.
MESSAGE "This took" TIME - iStart "seconds" VIEW-AS ALERT-BOX.
如果您想跟踪多次,那么输出到日志文件可能更好,而不是使用 MESSAGE-box,它将停止执行直到被点击。
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE STREAM str.
OUTPUT STREAM str TO c:\temp\timing.txt.
ETIME(TRUE).
/*
Fake loop
*/
DO i = 1 TO 20:
PAUSE 0.1.
PUT STREAM str UNFORMATTED "Timing no " i " " ETIME "ms" SKIP.
END.
OUTPUT CLOSE.
您可以按照您的要求进行操作(只需遵循 JensD 的建议),但使用分析器可能会更好。您可以轻松地为代码片段添加分析:
assign
profiler:enabled = yes
profiler:description = "description of this test"
profiler:profiling = yes
profiler:file-name = "filename.prf"
.
/* this is deliberately awful code that should take a long time to run */
for each orderline no-lock:
for each order no-lock:
for each customer no-lock:
if customer.custNum = order.custNum and orderLine.orderNum = orderLine.orderNum then
. /* do something */
end.
end.
end.
/* end of test snippet */
assign
profiler:enabled = no
profiler:profiling = no
.
profiler:write-data().
然后您可以将该 prf 文件加载到分析工具中。具体细节取决于您的开发环境——如果您使用的是最新版本的 PSDOE,则包含一个 Profiler 分析器,如果没有,您可能需要下载 ProTop https://demo.wss.com/download.php 并使用 lib/zprof_topx.p.
中包含的简单报告最终您会发现,您的一个或多个 FOR EACH 语句几乎肯定使用了与可用索引不匹配的 WHERE 子句。
要解决此问题,您需要确定实际选择了哪些索引并查看索引选择规则。可以在此处找到关于该主题的一些优秀 material:http://pugchallenge.org/downloads2019/303_FindingData.pdf
如果您不想费心阅读那篇文章,那么您至少应该看一下实际的索引选择,如下所示:
compile program.p xref program.xref
所选指数是否符合您的预期? WHOLE-INDEX(又名 "table scan")出现了吗?