我有SELECT
喜欢
SELECT t1.A,
t2.A,
t1.B,
t2.B,
case when v_val2 < sysdate
then null
else t2.D
end
from t1
left join t2
on t1.C = t2.C and t2.D = p_val1
where t2.ref_date = p_val2
其中 p_val1 和 p_val2 是params。真正的SELECT
更复杂,并且连接表有1.4亿行或更多。
如何在多个地方重复使用此选择?现在我在Business Object Report,VIEW,Insert和spool文件中使用它。我试图创建VIEW但没有params它太慢了。
我搜索了使用参数查看的内容,但是在问{TOM}中的this主题中,结论是没有这样的内容。
更新
p_val1 可以是4个固定值(如'A','B','C','D'),但 p_val2 更复杂,因为它是加载日期(加载数据的日期)。大约有500个历史加载日期,之后加载成为每日。每个报告,输出等都必须按日期进行。
答案 0 :(得分:3)
您的查询没有什么复杂的。我认为没有理由为什么在使用相同的标准调用时,视图应该比原始查询慢。
视图没有参数:
create view my_view as
select
t2_d, t2_ref_date,
t1.a as t1_a, t2.a as t2_a, t1.b as t1_b, t2.b as t2_b,
case when v_val2 < sysdate then null else t2.d end as e
from t2
join t1 on t1.c = t2.c;
当在查询中使用时,它应该导致相同的执行计划和与原始查询相同的性能:
select t1_a, t2_a, t1_b, t2_b, e
from my_view
where t2_ref_date = p_val2
and t2_d = p_val1;
你真的尝试过吗?我真的无法想象为什么这应该慢一些。
DBMS可以通过ref_date
和D
访问T2记录,然后加入T1。因此我改变了FROM
子句中表的顺序如下。 (我已经在上面的视图中做了这个。)这只是为了便于阅读。它仍然是同一个查询。
SELECT
t1.A,
t2.A,
t1.B,
t2.B,
case when v_val2 < sysdate then null else t2.D end
from t2
join t1 on t1.C = t2.C
where t2.ref_date = p_val2
and t2.D = p_val1
要使此查询快速运行,我建议使用以下索引:
create index idx_t2 on t2(ref_date, d, c);
create index idx_t1 on t2(c);
甚至更好地覆盖索引:
create index idx_t2 on t2(ref_date, d, c, a, b);
create index idx_t1 on t2(c, a, b);
当然,您的真实查询可能会有所不同。不是因为有很多行或很多表,但在您的示例中,我可以轻松选择有问题的两列。因此优化器可以直接使用它们来应用WHERE子句。但是,如果您的查询包含子查询中的聚合,例如在聚合之前应用条件的情况,则无法再使用视图提前应用它。
在不知道真实查询的情况下提供建议很难。也许编写流水线函数对你来说是更好的选择。
答案 1 :(得分:1)
创建功能。你可以在多个地方使用
CREATE OR REPLACE FUNCTION SampleFunction1(p_val1 in varchar2,p_val2 in varchar2 )
RETURN sys_refcursor
is
l_rc sys_refcursor;
begin
open l_rc
for
SELECT t1.A,t2.A,t1.B,t2.B, case when v_val2 < sysdate then null else t2.D end
from t1
join t2
on t1.C = t2.C and t2.D = p_val1
where t2.ref_date = p_val2;
return l_rc;
end;
答案 2 :(得分:0)
我的回答(最接近我并清楚我并且可能不是最佳选择)是创建用户定义的类型和第一类型的表格,如:
CREATE TYPE my_type AS OBJECT
( a VARCHAR2(20)
, b VARCHAR2(20)
, c VARCHAR2(20)
, d VARCHAR2(20)
, e VARCHAR2(20)
) ;
输入 my_type 的类型:
create TYPE T_my_type AS TABLE OF my_type ;
之后(感谢@ user9405863)我创建了返回 T_my_type 的函数(而不是 sys_refcursor ):
create or replace function myFunc(p_val1 varchar2, p_val2 date)
RETURN T_my_type is
v_T_my_type T_my_type ;
BEGIN
SELECT my_type (t1.A,t2.A,t1.B,t2.B, case when v_val2 < sysdate then null else t2.D end)
BULK collect INTO v_T_my_type
from t1
join t2
on t1.C = t2.C and t2.D = p_val1
where t2.ref_date = p_val2;
RETURN ttv_T_my_type
END;
在该功能中,我只是将结果列投射到 my_type ,并使用 BULK收集INTO 获得结果。
最后,当我执行:
select *
from table(myFunc('A', '13.04.2018'));
结果是我的预期。
<强> COMMENT 强>
如果你说出你对这个解决方案的看法以及它的利弊,我会很高兴。