我有一个Oracle视图(使用11gR2),它是其他三个视图的连接,即:
create or replace view main_vw as
select a.*, b.*, c.*
from a_vw a, b_vw b, c_vw c
where a.b_id = b.b_id
and a.c_id = c.c_id
执行“select * from main_vw”会挂起几个小时,而EXPLAIN PLAN会显示一个非常低效的查询计划。然而,如果创建逻辑上等效的步骤:
create table a_tbl as select * from a_vw;
create table b_tbl as select * from b_vw;
create table c_tbl as select * from c_vw;
select a.*, b.*, c.*
from a_tbl a, b_tbl b, c_tbl c
where a.b_id = b.b_id and a.c_id = c.c_id;
所有四个陈述都在5秒内完成。
有没有什么方法可以使用提示或其他东西来让Oracle的优化器首先评估子视图,然后将它们加入,就好像它们是表一样?
我看过提示'QB_NAME','NO_EXPAND','NO_REWRITE'无济于事......
注意:此示例中的a_vw,b_vw和c_vw是非常复杂的查询,它们共同引用基表。它们还引用了一个设置表,其内容在会话级别自定义并影响返回的内容。所以,我无法从这些视图中创建表。
答案 0 :(得分:2)
使用create or replace view main_vw as
select a.*, b.*, c.*
from
(select * from a_vw where rownum >= 1 /*prevent transformations*/) a,
(select * from b_vw where rownum >= 1 /*prevent transformations*/) b,
(select * from c_vw where rownum >= 1 /*prevent transformations*/) c
where a.b_id = b.b_id
and a.c_id = c.c_id
强制Oracle独立评估内联视图。
ROWNUM
起初看起来很奇怪。 {{1}}似乎没有做任何事情。但ROWNUM
是一个特殊的伪列,用于排序"可以影响视图优化"。实际上,它会阻止所有优化,并且是完全隔离代码的唯一安全方法。此方法对于类型安全也很有用,例如实体 - 属性 - 值模式,其中所有内容都存储为字符串,并且必须按特定顺序处理。
正如您已经发现的那样,提示很难做到正确。即使你现在确实得到了它们,但是当将来另一个开发人员修改查询时,他们很有可能无法正常工作。为了防止他们删除这个神秘的谓词,请务必添加评论。
这不一定能解决根性能问题,但它至少应该使指数更容易解决。总体解释计划应包括与每个内联视图的解释计划相匹配的三个部分。如果每个内联视图运行良好,您只需要担心它们之间的两个连接。