在Progress 4GL中使用不等式查询记录的最快方法是什么?例如,如果我需要找到状态字段与“MI”不匹配的所有记录,我将如何编写以获得最佳性能以及为什么?
我被告知的各种解决方案包括使用更广泛或不同的索引,然后使用IF语句,以避免使用不等式,例如:
FOR EACH record NO-LOCK:
IF record.state = "MI" THEN NEXT.
/*do stuff*/
END.
我被告知要避免使用NE
语句,因为它们会导致性能下降,
FOR EACH record NO-LOCK
WHERE record.state NE "MI":
/*do stuff slowly, apparently*/
END.
但我也被告知使用OR也是邪恶的。
FOR EACH record NO-LOCK
WHERE record.state = "WI" OR "AL":
/*didn't write all 49 minus MI for space*/
END.
我没有获得实质性证据证明为什么这三者中的任何一个都会优越,而且我的开发环境中没有足够的数据来测试我正在研究的实际情况。
答案 0 :(得分:2)
这完全取决于您的查询与可用索引的匹配程度。
你的第一个例子做了所谓的"表扫描" - 在进行IF之前,它会查看表中的每条记录,看看它是否是您想要的记录。大多数情况下,这是不您想要的,特别是如果表格很大或经常查询。
等于" ="是最高效的,特别是当您对要查询的字段或字段有索引时。
" OR"可能是邪恶的如果它与" AND"像这样:
WHERE customer.AmountDue > SomeValue AND
(customer.state = "MI" OR customer.state = "WI").
原因是数据库引擎无法使用OR进行任何索引查找,因此它将解析">"运算符,然后检查匹配">"的每条记录。看看它是否与两个州中的任何一个相匹配。
这可以通过重构WHERE来解决:
WHERE (customer.AmountDue > SomeValue AND customer.state = "MI") OR
(customer.AmountDue > SomeValue AND customer.state = "WI").
使用这种结构,db引擎有两个AND短语,它可以解析为一组较小的结果,将两个列表合并在一起,最终结果是一组记录供查询遍历。这比在问题的第一部分中使用OR快得多 。
这一切都归结为匹配您要查询的表上的索引的查询。如果索引与您正在寻找的内容完全匹配,那么它的速度会比索引与您的查询部分匹配的索引要快得多,或者如果有的话。根本没有匹配的索引。
您需要做的是查看在不同的PUG挑战赛会议上发表的一些精彩演讲。您可以在PUG Challenge Americas上找到有关索引选择的演示文稿:
pugchallenge.org/downloads2015.html
您可以在以前的活动"中找到PUG Challenge EMEA上的演示文稿。 http://pugchallenge.eu
的标签 祝你好运!答案 1 :(得分:2)
这一切都取决于你真正想要做什么以及真正的数据和索引究竟是什么。
幸运的是,您可以使用类似于以下内容的线束测试这些内容:
define variable i as integer no-undo.
define variable lr as integer no-undo.
find _myconnection no-lock.
find _userio no-lock where _userio-id = _myconn-userid + 1.
lr = _userio-dbaccess.
for each metric-desc no-lock /* query to test goes here... */
where db-id < 1600 or db-id > 1600:
i = i + 1.
end.
find _userio no-lock where _userio-id = _myconn-userid + 1.
lr = _userio-dbaccess - lr.
display lr i.
在这种情况下,我有一个名为&#34; metric-desc&#34;的表。它恰好有一个索引,其前导组件是一个名为&#34; db-id&#34;的字段。有点像有一个名为&#34; state&#34;。
的字段它有13,358条记录。
有52条记录的db-id = 1600(我凭空取出1600,而不是状态=&#34; MI&#34;)。
如果我注释掉WHERE子句并阅读整个内容,我会得到26,994&#34;逻辑读取&#34; (索引条目加记录)这是数据库引擎解决查询的工作。
如果我使用&#34; db-id&lt;&gt; 1600&#34; (类似于&#34;州&lt;&gt;&#39; MI&#39;&#34;在您的示例中)我得到相同的结果 - 扫描整个表格。
如果我将where子句替换为显示的OR,则需要26,892次逻辑读取 - 不读取db-id = 1600的记录。
就一般的经验法则而言,&#34; =&#34;是你的朋友,&#34;&lt;&gt;&#34;通常很糟糕(不是)。如果你能想出一种表达某种东西的方式&#34; =&#34;这将是最好的。范围匹配(&#34;&lt;&#34;,&#34;&lt; =&#34;,&#34;&gt;&#34;,&#34;&gt; =&#34;不是同样好,但它们不如&#34;&lt;&gt;&#34;)或者可能没问题 - 这取决于索引以及如何将查询放在一起。
最重要的索引规则是尽可能多地使用前导组件上的相等匹配项。一旦你离开那条规则,你就会妥协。