我发现在Progress 10.1中,当在查询中使用多个索引时,数据库将使用索引列表中的第一个索引,而不是最优化的索引,也不是这两个索引的子集。
有其他人经历过吗?
=============================================
定义了几个索引,但我们正在研究的两个索引是:XIE1cac_role_personowning_entity_a助记符owning_entity_key角色密钥
XIE2cac_role_person合同_ objperson_role_code生效日期
最初,我的代码如下,它使用了第一个索引,该索引返回了一个更大的数据集
FOR EACH cac_role_person NO-LOCK
WHERE cac_role_person.contract_obj = cbm_contract.contract_obj
AND cac_role_person.owning_entity_mnemonic = "BROKER"
AND (
(cac_role_person.effective_to_date > TODAY
AND cac_role_person.effective_to_date >=
cbm_contract_component.contract_component_start_date)
OR (cac_role_person.effective_to_date = ?
AND cac_role_person.effective_from_date <=
cbm_contract_component.contract_component_start_date)
):
所以我现在强制它使用第二个索引:
FOR EACH cac_role_person NO-LOCK USE-INDEX XIE2cac_role_person
WHERE cac_role_person.contract_obj = cbm_contract.contract_obj
AND cac_role_person.owning_entity_mnemonic = "BROKER"
AND (
(cac_role_person.effective_to_date > TODAY
AND cac_role_person.effective_to_date >=
cbm_contract_component.contract_component_start_date)
OR (cac_role_person.effective_to_date = ?
AND cac_role_person.effective_from_date <=
cbm_contract_component.contract_component_start_date)
):
第一个代码在30小时内完成了约4000个修复,改进后在12小时内修复了70000个。(循环是更大部分的一部分,但这只是我将处理速度提高17倍所需的更改
在某些情况下,程序员可以做出比编译器更好的索引选择。但它通常非常罕见。
如果不知道所有实际的索引定义(您没有提供),就不可能完全评估编译器可以选择哪些索引。考虑到你分享的内容,选择遵循规则(见下文),但规则与你上面描述的不同。
如果没有关于数据分布的数据,就不可能判断所选索引是"最佳"还是最佳。尽管已经说过,像"BROKER"这样具有值的字段似乎比"contract_obj"更不精致,这似乎是直观的。但这只是猜测。
Progress 4GL引擎可以使用多个索引来解析查询,但这并不意味着它会这样做,也不意味着如果这样做,结果一定会更好。要想知道它是否做到了,您需要使用XREF进行编译并查看结果。
4GL引擎使用静态的编译时索引选择。您可以在此处找到有关规则的一些非常详细的信息:http://pugchallenge.org/downloads/352_Pick_an_Index_2013.pdf
最重要的规则是:最大限度地提高领先组件上相等匹配的深度。您有两个可能的相等匹配项:
cac_role_person.contract_obj = cbm_contract.contract_obj
cac_role_person.owning_entity_mnemonic = "BROKER"
因此,您的"最佳"索引(在不了解任何数据分布的情况下)几乎肯定是以这两个字段作为主要组件的索引。理想情况下,您的第三个组件是cac_role_person.effective_to_date字段。如果没有任何符合该条件的索引,则可能需要考虑添加一个。
您所显示的两个索引中的每一个都有一个与前导组件相等的匹配项。因此,它们具有同等的力量。平局决胜标准开始发挥作用——如果其中一个被指定为"主要"指数,它就会获胜。否则,由于没有指示BY标准,因此按字母顺序获胜。
如果您缺少适当的索引,或者您有意进行表扫描,那么指定最小索引通常是最快的。您可以通过查看的输出来确定
proutil dbName -C dbanalys > dbName.dba
块数最少的索引就是您想要的索引。如果它们的大小大致相同,请选择最高的"利用率"。
FWIW——SQL引擎使用基于成本的优化器。然而,如果你想让统计数据正常工作,你必须定期更新统计数据。(这对您的4GL查询没有帮助。)(4GL中可用的SQL语法是嵌入式SQL-89,它不知道基于成本的优化器,这也没有帮助。试图在4GL会话中使用SQL是通往无尽挫折的道路——不要去那里。)