Progress 4GL编译器为何优先选择主唯一索引而非自定义索引?
为何自定义索引未被自动选用,反而主索引被优先选择?
我为查询定义了包含WHERE子句所有字段的自定义索引vdmod_idx1,但通过XREF查看发现编译器自动选择了主唯一索引vdlist,只有强制指定时才会使用vdmod_idx1,想知道原因。
查询语句
for last vdhist no-lock where vdhist.vddomain = dom and vdclassification = 1 and vdhist.vdlist = prlt and vdhist.vdprod_ln = prodLn and vdhist.vdcurr = curr and vdhist.vdpart = part and vdhist.vdum = tt_um and vdhist.vdstart = date(tt_start) and vdmod_date > 01/01/2021 and vdmod_time > 45556: end.
索引定义
pu vdlist 10 + vddomain + vdclassification + vdlist + vdprod_ln + vdcurr + vdpart + vdum + vdstart + vdcrt_date + vdlocal_rsn vdmod_idx1 10 + vddomain + vdclassification + vdlist + vdprod_ln + vdcurr + vdpart + vdum + vdstart + vdmod_date + vdmod_time
原因分析
- 统计信息缺失或过时:Progress查询优化器依赖表的统计信息判断索引效率。如果
vdmod_idx1相关字段(尤其是vdmod_date和vdmod_time)的统计信息未更新,优化器无法准确评估该索引的过滤能力,会倾向选择统计信息更完善的主索引。 - 排序需求的匹配偏差:查询使用
for last需要返回符合条件的最后一条记录。主索引vdlist的后缀字段vdcrt_date、vdlocal_rsn被优化器判定为更适合排序取最后一条;而vdmod_idx1的后缀是vdmod_date和vdmod_time,优化器未识别到这两个字段的过滤+排序组合能更快定位目标记录。 - 主索引的默认优先级:Progress默认会优先考虑主唯一索引,当优化器无法明确判断自定义索引的性能优势时,会 fallback 到主索引——主索引的访问路径通常被数据库更“熟悉”。
- 范围条件的评估误差:优化器对
vdmod_date > 01/01/2021和vdmod_time > 45556这两个范围条件的过滤效果判断有误,如果它认为过滤后数据量仍很大,会觉得主索引遍历更高效。
解决建议
- 更新表统计信息:执行
UPDATE STATISTICS FOR TABLE vdhist;,让优化器准确评估索引效率。 - 调整索引字段顺序:若
vdmod_date和vdmod_time过滤性更强,可将其提前到索引前缀(需保证前序字段为等值条件),提升索引过滤效率。 - 验证性能差异:强制使用
vdmod_idx1后对比执行时间,确认其性能优势,再通过优化统计信息引导优化器自动选择。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

