我的应用程序使用必须保持通用的视图(无过滤器),其中包括分析函数RANK
和DENSE_RANK
。例如,我有一个视图MYVIEW
:
SELECT
RANK() OVER (PARTITION BY FIELD1 ORDER BY FIELD2) RANK,
FIELD2,
FIELD3
FROM TABLE1;
我的应用程序然后在运行时应用必要的过滤器,即
SELECT * FROM MYVIEW WHERE FIELD3 IN ('a','b','c');
我的查询速度非常快,没有RANK功能,但是速度很慢(2分钟以上)(我得到了正确的结果,只是很慢)。基础表有250,000多行,我无法控制其设计。我无法进一步分区。因此它很慢,因为每次调用视图时它都会为FIELD1中的每个唯一条目创建分区?还有其他方法可以避免吗?关于如何加快速度的任何建议?
答案 0 :(得分:0)
正如评论中所提到的,在视图中使用您的分析功能,Oracle无法采取任何快捷方式(谓词推送),因为
因此,根据您提供的详细信息,您的查询需要按照以下方式进行评估:
SELECT *
FROM (
SELECT
RANK() OVER (PARTITION BY FIELD1 ORDER BY FIELD2) RANK,
FIELD2,
FIELD3
FROM TABLE1
) myview
WHERE <condition>; -- rankings are not affected by external conditions
和不这个:
SELECT * FROM (
SELECT
RANK() OVER (PARTITION BY FIELD1 ORDER BY FIELD2) RANK,
FIELD2,
FIELD3
FROM TABLE1
WHERE FIELD3 IN ('a','b','c') -- ranking is affected by the conditions
)
那么,有没有办法让它更快?也许
不是通常意义上的。由于视图本身没有条件,它将进行全表扫描以考虑排名的所有行,并且在应用WHERE子句时,使用索引进行过滤已经太晚了。
但是,如果你有一个&#34;覆盖的索引&#34;查询,即只有正在使用的列的索引(例如,FIELD1,FIELD2,FIELD3的顺序),索引可以用作表的较小版本(而不是FULL TABLE SCAN,计划将显示INDEX快速全扫描。)作为奖励,因为它已经排序,它可以有效地计算FIELD1上的分区,然后在每个分区内的FIELD2上进行排序。
另一种选择是将其作为物化视图,但如果您的数据经常变化,那么保持最新状态可能会非常痛苦。
最后一个想法是与“穷人”相似的东西&#34;在分区选项的日期之前使用的分区。 (对不起,我找不到描述这个的好链接,但也许你以前听说过。)
在以下情况下,这只是一个选项:
鉴于Oracle在涉及分析函数时似乎不利于推断谓词,我并没有给出很高的成功概率。
如果您想了解更多相关信息,请与我们联系。