nvl(x,y) 运行机制:
当x不为空,还会计算y。
--因为视图里,有两个自定义函数:
实验验证:
create or replace function f_nvl
return varchar2
is
v_char varchar2(22);
begin
v_char := 'run!';
dbms_output.put_line(v_char);
return v_char;
end;
/
select nvl(a, f_nvl()) a from (select 'x' a from dual);
A
---------------------------
x
run!
SQL> --说明执行了自定义函数
select decode(a, null,f_nvl(),a) a from (select 'x' a from dual);
create or replace function f_nvl
return varchar2
is
v_char varchar2(22);
begin
v_char := 'run!';
dbms_output.put_line(v_char);
return v_char;
end;
/
select nvl(a, f_nvl()) a from (select 'x' a from dual);
A
---------------------------
x
run!
SQL> --说明执行了自定义函数
select decode(a, null,f_nvl(),a) a from (select 'x' a from dual);
A
--------------------
x
SQL> --decode没有输出"run!",说明它不执行自定义函数。
--------------------
x
SQL> --decode没有输出"run!",说明它不执行自定义函数。
案例:
--case2:
--一个统计结果的代码,每个月执行一次
SELECT PROVCODE AS PROV_ID, --省份
AREACODE AS AREA_ID, --地区
LIMITINADDLIST AS MAIL_NOTIFY_TYPE_ID,
COUNT(DISTINCT USERNUMBER) AS LIMITINADDLIST_UCNT
FROM ODSVIEW. VW_ODS_MAIL_NOTIFY_LIMIT
WHERE SERVICEID = 10
AND STAT_MONTH = :B1
GROUP BY PROVCODE, AREACODE, LIMITINADDLIST;
机器的配置:256G 内存,RAC, AIX 128CPU
却要跑4个小时,why ?
--一个统计结果的代码,每个月执行一次
SELECT PROVCODE AS PROV_ID, --省份
AREACODE AS AREA_ID, --地区
LIMITINADDLIST AS MAIL_NOTIFY_TYPE_ID,
COUNT(DISTINCT USERNUMBER) AS LIMITINADDLIST_UCNT
FROM ODSVIEW. VW_ODS_MAIL_NOTIFY_LIMIT
WHERE SERVICEID = 10
AND STAT_MONTH = :B1
GROUP BY PROVCODE, AREACODE, LIMITINADDLIST;
机器的配置:256G 内存,RAC, AIX 128CPU
却要跑4个小时,why ?
--因为视图里,有两个自定义函数:
create or replace view odsview.
vw_ods_mail_notify_limit as
Select STAT_MONTH ,
USERNUMBER , --手机号
SERVICEID ,
nvl(PROVCODE, getprovcode(USERNUMBER)) AS PROVCODE ,
nvl(AREACODE , getareacode(USERNUMBER)) AS AREACODE ,
NOTIFYTYPE ,
CASE
WHEN notifytype<>9 THEN NOTIFYTYPE
WHEN notifytype = 9 AND (limitinaddlist =-1 OR limitinaddlist IS null) THEN 0
ELSE limitinaddlist
END limitinaddlist,
CASE
WHEN notifytype<>9 THEN NOTIFYTYPE
WHEN notifytype = 9 AND (LIMITNOTINADDLIST =-1 OR LIMITNOTINADDLIST IS null) THEN 0
ELSE LIMITNOTINADDLIST
END LIMITNOTINADDLIST
From datasync_prc.ODS_MAIL_NOTIFY_LIMIT; --6亿数据,字段少,13个G
nvl()那两列是为了确认省份,地市是否为空
datasync_prc.ODS_MAIL_NOTIFY_LIMIT 这里为什么没有算好?
因为有垃圾数据,6亿里面 只有几条数据没有省份、地区。
优化方案: 将nvl() 函数用decode() 替换。
--by 七年
Select STAT_MONTH ,
USERNUMBER , --手机号
SERVICEID ,
nvl(PROVCODE, getprovcode(USERNUMBER)) AS PROVCODE ,
nvl(AREACODE , getareacode(USERNUMBER)) AS AREACODE ,
NOTIFYTYPE ,
CASE
WHEN notifytype<>9 THEN NOTIFYTYPE
WHEN notifytype = 9 AND (limitinaddlist =-1 OR limitinaddlist IS null) THEN 0
ELSE limitinaddlist
END limitinaddlist,
CASE
WHEN notifytype<>9 THEN NOTIFYTYPE
WHEN notifytype = 9 AND (LIMITNOTINADDLIST =-1 OR LIMITNOTINADDLIST IS null) THEN 0
ELSE LIMITNOTINADDLIST
END LIMITNOTINADDLIST
From datasync_prc.ODS_MAIL_NOTIFY_LIMIT; --6亿数据,字段少,13个G
nvl()那两列是为了确认省份,地市是否为空
datasync_prc.ODS_MAIL_NOTIFY_LIMIT 这里为什么没有算好?
因为有垃圾数据,6亿里面 只有几条数据没有省份、地区。
优化方案: 将nvl() 函数用decode() 替换。
--by 七年