Access中带WHERE子句的UNION查询无法利用索引导致全表扫描的性能优化求助
各位好,我现在遇到了Access里的一个棘手性能问题,想请教大家有没有更优雅的解决方案。
先给大家还原下问题场景:
我有一张核心业务表tblFigures,结构和对应的索引如下:
CREATE TABLE tblFigures ( EntryDate DATETIME, AmountType NUMBER, Amount DOUBLE ); CREATE INDEX idxAmountType ON tblFigures (AmountType);
直接针对这张表加WHERE条件查询时,Jet引擎会正常命中idxAmountType索引,从JetShowPlan的日志里能明确看到这一点,速度完全没问题:
SELECT * FROM tblFigures WHERE AmountType = 1;
但如果我先创建一个UNION ALL的查询(命名为qryFiguresUnion):
SELECT * FROM tblFigures UNION ALL SELECT * FROM tblFigures;
再基于这个联合查询加WHERE条件过滤时,就会触发全表扫描,完全不走索引,性能直接暴跌:
SELECT * FROM qryFiguresUnion WHERE AmountType = 1;
我自己推测原因可能是:联合查询的结果是内存中的虚拟数据集,没有持久化到数据库,自然也就没有索引可以复用?(当然这个猜想不一定对,欢迎大家指正!)
这个性能问题对我的应用影响很大,具体的业务背景是这样的:
表中包含三种金额类型(1、2、3),后续的计算模块里,用户可以选择基于单个类型进行计算,也可以选择基于三个类型的总和进行计算。
最开始我尝试的方案是:把tblFigures的原始数据,和「按EntryDate汇总三个类型金额总和」的记录做UNION合并,用这个联合查询作为后续计算的数据源。功能倒是正常实现了,但因为全表扫描的问题,速度慢到无法接受。
后来我想到了一个折中的思路:先把三个类型的总和计算出来,插入到tblFigures中,用金额类型4来标记这些汇总数据,之后直接用tblFigures作为后续计算的数据源。这样Jet引擎应该能正常使用索引,速度肯定有保障,但我对这个方案不太满意——汇总数据属于冗余数据,和原始数据混在一起总觉得不够严谨。
所以想请教各位大佬,有没有更好的解决方案?既能避免冗余数据,又能让查询利用上索引,提升性能?麻烦大家给点思路,谢谢了!
内容来源于stack exchange

