任何人都可以解释一下为什么当我运行一个正在进行的查询时,它只在一个表上运行它只在几秒钟内运行,当我运行一个查询作用于多个表时,它会在几个小时内运行。我使用的是否有任何错误的东西?
我的最后一次尝试是:
FOR EACH multipos.mp_loja NO-LOCK,
EACH multipos.mp_acmp NO-LOCK,
EACH multipos.mp_mvlj NO-LOCK
WHERE mp_mvlj.lj_cod = mp_loja.lj_cod
AND mp_mvlj.mvl_dtmov = mp_acmp.mvl_dtmov:
/* EXPORT ... */
END.
到现在为止,我改为:
FOR EACH multipos.mp_mvlj NO-LOCK WHERE mp_mvlj.mvl_dtmov = 04/20/2015,
EACH multipos.mp_loja NO-LOCK WHERE mp_loja.lj_cod = mp_mvlj.lj_cod,
EACH multipos.mp_acmp NO-LOCK WHERE mp_acmp.lj_cod = mp_mvlj.lj_cod
AND mp_acmp.mvl_dtmov = mp_mvlj.mvl_dtmov:
/* EXPORT */
END.
现在,这是最有效的方式吗?
答案 0 :(得分:1)
您没有指定将mp_loja加入mp_acmp的条件。
所有关于可用的索引和调用它们的WHERE子句都是关于它的。为了获得良好的性能,您必须使用作为索引的主要组件的字段。任何不足都会导致表格扫描。
使用XREF编译代码。您将在输出中看到WHOLE-INDEX。这意味着您正在执行表扫描。如果你在连接的每次迭代中扫描整个表,那将是非常非常痛苦的。如果你做到这两个层次,那将是完全荒谬的。
WHERE子句中的字段必须是所选表中索引的前导组件(或唯一组件)。否则Progress不能对查询进行括号,并且必须进行表扫描以评估条件。
理想情况下,mp_mvlj表上有一个唯一索引,lj_cod和mvl_dtmov是唯一的字段。
您还需要一个将mp_loja连接到mp_acmp的唯一索引。
仔细查看WHERE子句和可用的索引。如果没有合适的索引,您可能需要添加一个索引。
您当前的代码相当于3个嵌套的FOR EACH循环:
for each mp_loja no-lock: /* no WHERE, scan the entire table */
for each mp_acmp no-lock: /* no WHERE, scan the entire table ON EVERY ITERATION of the outer loop which is scanning it's entire table!!! */
for each mp_mvlj no-lock
where mp_mvlj.lj_cod = mp_loja.lj_cod
and mp_mvlj.mvl_dtmov = mp_acmp.mvl_dtmov: /* WHERE of unknown quality, but we are executing it on every iteration of the two outer loops */
/* export ... */
end.
end.
end.
我不相信我尝试使用“sports2000”数据库进行实验。在我的副本中有3,948个订单记录和13,970个订单行记录。
define variable i as integer no-undo.
for each order no-lock,
each orderline no-lock:
i = i + 1.
end.
display i.
我得到i = 55,153,560。恰好是3,948 * 13,970。 非常需要很长时间才能执行。
与之对比:
define variable i as integer no-undo.
for each order no-lock,
each orderline no-lock where orderline.ordernum = order.ordernum:
i = i + 1.
end.
display i.
更快,更快。 i = 13,942(我的sports2000副本中有28个孤立的订单行......)