UDF的次优性能 [英] Sub-optimal performance of a UDF

查看:122
本文介绍了UDF的次优性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我最近在SQl中编写了一个用户定义的函数,在db2中运行它和

工作正常。但我似乎得到一个警告说,性能是次优的。$ / b

这是警告信息:


SQL0437W此复杂查询的性能可能不是最佳的。原因

代码:

" 2"。 SQLSTATE = 01602


我已执行运行统计操作但仍然收到

警告。


有没有我需要查看的一系列内容获得最佳好处

表现?


谢谢

Mahesh

Hi

I recently wrote a user defined function in SQl to run in db2 and it
works fine. But I seem to get a warning saying that the performance is
sub-optimal.

Here is the warning message:

SQL0437W Performance of this complex query may be sub-optimal. Reason
code:
"2". SQLSTATE=01602

I have performed run statistics operation but am still getting the
warning.

Is there a list of things that I need to look into gain best
performance?

Thanks
Mahesh

推荐答案

我正在制作UDF代码,因为它可以帮助你们指出

我做错了什么。这是UDF代码:


CREATE FUNCTION RISK_EQUATION_1(@patient_id VARCHAR(36))

返回双倍

--- -------------------------------------------------- -------------------

- SQL UDF(标量)

-------- -------------------------------------------------- --------------

F1:BEGIN ATOMIC

DECLARE @x varchar(36);

DECLARE @z char;

DECLARE @hdl,@ family_history,@ smoke,@ waist double;

DECLARE x1,x2,x3,x4,x5,x6,GmaxScore,回答双倍;

DECLARE start_time,end_time,diff_time时间戳;


FOR myrow1 AS选择PATIENT_VISIT_ID来自

HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW其中PATIENT_ID = @patient_id DO

SET @x = myrow1.PATIENT_VISIT_ID;

END FOR;


FOR myrow2 AS从HEALTHCAREDB中选择RC_7_13_1_DFH .FAMILY_HISTORY

其中PATIENT_ID = @patient_id DO

SET @z = myrow2.RC_7_13_1_DFH;

结束;


FOR myrow3 AS从HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW中选择RCO_4_01_0_2_W,RLD_5_06_3_HDLCL,

RL_14_02_1_SS

PATIENT_VISIT_ID = @x DO

SET @waist = myrow3.RCO_4_01_0_2_W;

SET @hdl = myrow3.RLD_5_06_3_HDLCL;

SET @smoke = myrow3.RL_14_02_1_SS ;

结束;


如果@z =''Y''

那么设置@family_history = 1;

ELSE SET @family_history = 0;

END IF;


set x1 = @family_history;

设置x2 = @family_history;

设置x3 = @smoke;

设置x4 = 0;

设置x5 = 0;


设置x2 = x3 - x2;

设置x1 = HEALTHCAREDB.MAXIMUM(x1,x2);

设置x2 = @hdl;

设置x1 = HEALTHCAREDB.MAXIMUM(x1,x2);


设置x2 = 1.735981;

设置x3 = @family_history;

设置x2 = x3 - x2;


如果@waist = 104.0那么

设置x3 = 1;

其他se t x3 = 0;

结束如果;


设置x4 = @smoke;

如果@waist = 103则

设置x5 = 1;

否则设置x5 = 0;

结束if;


设置x6 = 1.15732;

如果x6> = x5那么

设置x5 = 1;

否则设置x5 = 0;

结束if;


设置x4 = HEALTHCAREDB.MAXIMUM(x4,x5);

设置x3 = x4 - x3;

设置x2 = x3 - x2;


if(x1!= 0)然后

设置x1 = x2 / x1;

否则设置x1 = 1;

结束if;


if(@waist = 103.0)then

set x2 = 1;

否则设置x2 = 0;

结束if;


设置x1 = x2 - x1;

设置x2 = @hdl;


设置x1 = x2 - x1;


if(@waist = 104)then

设置x2 = 1;

否则设置x2 = 0;

结束if;


设置x3 = 1.374318;


if(@waist = 104)然后

设置x4 = 1;

else set x4 = 0;

结束if;

设置x3 = x3 + x4;

设置x2 = x2 + x3;

设置x1 = HEALTHCAREDB.MAXIMUM(x1,x2);


设定GmaxScore = x1;


设定x1 = -0.4324524 * GmaxScore + 3.230582;


SET答案=(1 /(1 + x1));


返回(答案);


结束
I am producing the UDF code as it may help you guys in pointing out
what I am doing wrong. Here is the UDF code:

CREATE FUNCTION RISK_EQUATION_1( @patient_id VARCHAR(36) )
RETURNS double
------------------------------------------------------------------------
-- SQL UDF (Scalar)
------------------------------------------------------------------------
F1: BEGIN ATOMIC
DECLARE @x varchar(36);
DECLARE @z char;
DECLARE @hdl, @family_history, @smoke, @waist double;
DECLARE x1, x2, x3, x4, x5, x6, GmaxScore, answer double;
DECLARE start_time, end_time, diff_time timestamp ;

FOR myrow1 AS select PATIENT_VISIT_ID from
HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where PATIENT_ID = @patient_id DO
SET @x = myrow1.PATIENT_VISIT_ID;
END FOR;

FOR myrow2 AS select RC_7_13_1_DFH from HEALTHCAREDB.FAMILY_HISTORY
where PATIENT_ID = @patient_id DO
SET @z = myrow2.RC_7_13_1_DFH;
END FOR;

FOR myrow3 AS select RCO_4_01_0_2_W, RLD_5_06_3_HDLCL,
RL_14_02_1_SS from HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where
PATIENT_VISIT_ID = @x DO
SET @waist = myrow3.RCO_4_01_0_2_W;
SET @hdl = myrow3.RLD_5_06_3_HDLCL;
SET @smoke = myrow3.RL_14_02_1_SS;
END FOR;

IF @z = ''Y''
THEN SET @family_history = 1;
ELSE SET @family_history = 0;
END IF;

set x1 = @family_history;
set x2 = @family_history;
set x3 = @smoke;
set x4 = 0;
set x5 = 0;

set x2 = x3 - x2;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);
set x2 = @hdl;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);

set x2 = 1.735981;
set x3 = @family_history;
set x2 = x3 - x2;

if @waist = 104.0 then
set x3 = 1;
else set x3 = 0;
end if;

set x4 = @smoke;
if @waist = 103 then
set x5 = 1;
else set x5 = 0;
end if;

set x6 = 1.15732;
if x6 >= x5 then
set x5 = 1;
else set x5 = 0;
end if;

set x4 = HEALTHCAREDB.MAXIMUM(x4, x5);
set x3 = x4 - x3;
set x2 = x3 - x2;

if (x1 != 0) then
set x1 = x2 / x1;
else set x1 = 1;
end if;

if (@waist = 103.0) then
set x2 = 1;
else set x2 = 0;
end if;

set x1 = x2 - x1;
set x2 = @hdl;

set x1 = x2 - x1;

if (@waist = 104) then
set x2 = 1;
else set x2 = 0;
end if;

set x3 = 1.374318;

if (@waist = 104) then
set x4 = 1;
else set x4 = 0;
end if;
set x3 = x3 + x4;
set x2 = x2 + x3;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);

set GmaxScore = x1;

set x1 = -0.4324524 * GmaxScore + 3.230582;

SET answer = ( 1 / (1 + x1));

return ( answer );

END


Mahesh S写道:
Mahesh S wrote:

我正在制作UDF代码,因为它可以帮助你们指出

我做错了什么。这是UDF代码:


CREATE FUNCTION RISK_EQUATION_1(@patient_id VARCHAR(36))

返回双倍

--- -------------------------------------------------- -------------------

- SQL UDF(标量)

-------- -------------------------------------------------- --------------

F1:BEGIN ATOMIC

DECLARE @x varchar(36);

DECLARE @z char;

DECLARE @hdl,@ family_history,@ smoke,@ waist double;

DECLARE x1,x2,x3,x4,x5,x6,GmaxScore,回答双倍;

DECLARE start_time,end_time,diff_time时间戳;


FOR myrow1 AS选择PATIENT_VISIT_ID来自

HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW其中PATIENT_ID = @patient_id DO

SET @x = myrow1.PATIENT_VISIT_ID;

END FOR;
I am producing the UDF code as it may help you guys in pointing out
what I am doing wrong. Here is the UDF code:

CREATE FUNCTION RISK_EQUATION_1( @patient_id VARCHAR(36) )
RETURNS double
------------------------------------------------------------------------
-- SQL UDF (Scalar)
------------------------------------------------------------------------
F1: BEGIN ATOMIC
DECLARE @x varchar(36);
DECLARE @z char;
DECLARE @hdl, @family_history, @smoke, @waist double;
DECLARE x1, x2, x3, x4, x5, x6, GmaxScore, answer double;
DECLARE start_time, end_time, diff_time timestamp ;

FOR myrow1 AS select PATIENT_VISIT_ID from
HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where PATIENT_ID = @patient_id DO
SET @x = myrow1.PATIENT_VISIT_ID;
END FOR;



愚蠢的问题:你为什么在这里使用循环?一个简单的


SET @x =(SELECT ... FROM ... WHERE ... FETCH FIRST 1 ROWS only)


会完成与循环相同的任务。

Stupid question: why do you use a loop here? A simple

SET @x = ( SELECT ... FROM ... WHERE ... FETCH FIRST 1 ROWS ONLY )

would accomplish the same task as your loop.


FOR myrow2 AS从HEALTHCAREDB.FAMILY_HISTORY中选择RC_7_13_1_DFH

其中PATIENT_ID = @patient_id DO

SET @z = myrow2.RC_7_13_1_DFH;

END FOR;
FOR myrow2 AS select RC_7_13_1_DFH from HEALTHCAREDB.FAMILY_HISTORY
where PATIENT_ID = @patient_id DO
SET @z = myrow2.RC_7_13_1_DFH;
END FOR;



见上文。

see above.


FOR myrow3 AS选择RCO_4_01_0_2_W,RLD_5_06_3_HDLCL,

来自HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW的RL_14_02_1_SS

PATIENT_VISIT_ID = @x DO

SET @waist = myrow3.RCO_4_01_0_2_W;

SET @hdl = myrow3。 RLD_5_06_3_HDLCL;

SET @smoke = myrow3.RL_14_02_1_SS;

END FOR;
FOR myrow3 AS select RCO_4_01_0_2_W, RLD_5_06_3_HDLCL,
RL_14_02_1_SS from HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where
PATIENT_VISIT_ID = @x DO
SET @waist = myrow3.RCO_4_01_0_2_W;
SET @hdl = myrow3.RLD_5_06_3_HDLCL;
SET @smoke = myrow3.RL_14_02_1_SS;
END FOR;



见上文。

see above.


IF @z =''Y''

THEN SET @family_history = 1;

ELSE SET @family_history = 0;

END IF;


set x1 = @family_history;

set x2 = @family_history;

set x3 = @smoke;

set x4 = 0;

设置x5 = 0;


设置x2 = x3 - x2;

设置x1 = HEALTHCAREDB.MAXIMUM(x1,x2);

set x2 = @hdl;

set x1 = HEALTHCAREDB.MAXIMUM(x1,x2);
IF @z = ''Y''
THEN SET @family_history = 1;
ELSE SET @family_history = 0;
END IF;

set x1 = @family_history;
set x2 = @family_history;
set x3 = @smoke;
set x4 = 0;
set x5 = 0;

set x2 = x3 - x2;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);
set x2 = @hdl;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);



函数HEALTHCAREDB.MAXIMUM究竟是如何实现的?

How exactly is the function HEALTHCAREDB.MAXIMUM implemented?


set x2 = 1.735981;

设置x3 = @family_history;

设置x2 = x3 - x2;


如果@waist = 104.0那么

设置x3 = 1;

否则设置x3 = 0;

结束if;
set x2 = 1.735981;
set x3 = @family_history;
set x2 = x3 - x2;

if @waist = 104.0 then
set x3 = 1;
else set x3 = 0;
end if;



您应该考虑使用CASE表达式(此处和其他一些地方):


SET x3 = CASE

WHEN @waist = 104.0

那么1

ELSE 0

END;

也许你可以使用NULL而不是0(如果有意义的话)。

You should consider using CASE expressions (here and in a few other places):

SET x3 = CASE
WHEN @waist = 104.0
THEN 1
ELSE 0
END;
Maybe you could use NULLs instead of 0 (if it makes sense).


set x4 = @smoke;

if @waist = 103 then

设置x5 = 1;

否则设置x5 = 0;

结束if;


设置x6 = 1.15732;

如果x6> = x5那么

设置x5 = 1;

否则设置x5 = 0;

结束如果;


设置x4 = HEALTHCAREDB.MAXIMUM(x4,x5);

设置x3 = x4 - x3;

设置x2 = x3 - x2;


如果(x1!= 0)那么

设置x1 = x2 / x1;

else set x1 = 1;

end if;


if(@waist = 103.0)then

set x2 = 1;

else set x2 = 0;

end if;


设置x1 = x2 - x1;

设置x2 = @hdl;


设置x1 = x2 - x1;


if(@waist = 104)then

set x2 = 1;

else set x2 = 0;

结束if;


set x3 = 1.374318;


if(@waist = 104)then

设置x4 = 1;

否则设置x4 = 0;

结束if;


设置x3 = x3 + x4;

设置x2 = x2 + x3;

设置x1 = HEALTHCAREDB.MAXIMUM(x1,x2);


设置GmaxScore = x1;


设置x1 = -0.4324524 * GmaxScore + 3.230582;


SET答案=(1 /(1 + x1)) ;


返回(回答);


结束
set x4 = @smoke;
if @waist = 103 then
set x5 = 1;
else set x5 = 0;
end if;

set x6 = 1.15732;
if x6 >= x5 then
set x5 = 1;
else set x5 = 0;
end if;

set x4 = HEALTHCAREDB.MAXIMUM(x4, x5);
set x3 = x4 - x3;
set x2 = x3 - x2;

if (x1 != 0) then
set x1 = x2 / x1;
else set x1 = 1;
end if;

if (@waist = 103.0) then
set x2 = 1;
else set x2 = 0;
end if;

set x1 = x2 - x1;
set x2 = @hdl;

set x1 = x2 - x1;

if (@waist = 104) then
set x2 = 1;
else set x2 = 0;
end if;

set x3 = 1.374318;

if (@waist = 104) then
set x4 = 1;
else set x4 = 0;
end if;
set x3 = x3 + x4;
set x2 = x2 + x3;
set x1 = HEALTHCAREDB.MAXIMUM(x1, x2);

set GmaxScore = x1;

set x1 = -0.4324524 * GmaxScore + 3.230582;

SET answer = ( 1 / (1 + x1));

return ( answer );

END



- < br $>
Knut Stolze

DB2信息集成开发

IBM德国

--
Knut Stolze
DB2 Information Integration Development
IBM Germany


Knut Stolze写道:
Knut Stolze wrote:

Mahesh S写道:
Mahesh S wrote:

>我正在制作UDF代码,因为它可以帮助你们指出我做错了什么。这是UDF代码:

CREATE FUNCTION RISK_EQUATION_1(@patient_id VARCHAR(36))
RETURNS double
--------------- -------------------------------------------------- -------
- SQL UDF(Scalar)
---------------------------- --------------------------------------------
F1: BEGIN ATOMIC
DECLARE @x varchar(36);
DECLARE @z char;
DECLARE @hdl,@ family_history,@ smoke,@ waist double;
DECLARE x1,x2, x3,x4,x5,x6,GmaxScore,回答双倍;
DECLARE start_time,end_time,diff_time timestamp;

FOR myrow1 AS从
HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW中选择PATIENT_VISIT_ID,其中PATIENT_ID = @ patient_id DO
SET @x = myrow1.PATIENT_VISIT_ID;
END FOR;
>I am producing the UDF code as it may help you guys in pointing out
what I am doing wrong. Here is the UDF code:

CREATE FUNCTION RISK_EQUATION_1( @patient_id VARCHAR(36) )
RETURNS double
------------------------------------------------------------------------
-- SQL UDF (Scalar)
------------------------------------------------------------------------
F1: BEGIN ATOMIC
DECLARE @x varchar(36);
DECLARE @z char;
DECLARE @hdl, @family_history, @smoke, @waist double;
DECLARE x1, x2, x3, x4, x5, x6, GmaxScore, answer double;
DECLARE start_time, end_time, diff_time timestamp ;

FOR myrow1 AS select PATIENT_VISIT_ID from
HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where PATIENT_ID = @patient_id DO
SET @x = myrow1.PATIENT_VISIT_ID;
END FOR;



愚蠢的问题:你为什么在这里使用循环?一个简单的


SET @x =(SELECT ... FROM ... WHERE ... FETCH FIRST 1 ROWS only)


会完成与循环相同的任务。


Stupid question: why do you use a loop here? A simple

SET @x = ( SELECT ... FROM ... WHERE ... FETCH FIRST 1 ROWS ONLY )

would accomplish the same task as your loop.


> FOR myrow2 AS从HEALTHCAREDB.FAMILY_HISTORY中选择RC_7_13_1_DFH
其中PATIENT_ID = @patient_id DO
SET @z = myrow2.RC_7_13_1_DFH;
END FOR;
> FOR myrow2 AS select RC_7_13_1_DFH from HEALTHCAREDB.FAMILY_HISTORY
where PATIENT_ID = @patient_id DO
SET @z = myrow2.RC_7_13_1_DFH;
END FOR;



见上文。


see above.


> FOR myrow3 AS从HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW中选择RCO_4_01_0_2_W,RLD_5_06_3_HDLCL,
RL_14_02_1_SS
PATIENT_VISIT_ID = @x DO
SET @waist = myrow3.RCO_4_01_0_2_W;
SET @hdl = myrow3.RLD_5_06_3_HDLCL ;
SET @smoke = myrow3.RL_14_02_1_SS;
END FOR;
> FOR myrow3 AS select RCO_4_01_0_2_W, RLD_5_06_3_HDLCL,
RL_14_02_1_SS from HEALTHCAREDB.PATIENT_VISIT_INFO_VIEW where
PATIENT_VISIT_ID = @x DO
SET @waist = myrow3.RCO_4_01_0_2_W;
SET @hdl = myrow3.RLD_5_06_3_HDLCL;
SET @smoke = myrow3.RL_14_02_1_SS;
END FOR;



见上文。


see above.


>如果@z =''Y''
那么设置@family_history = 1;
ELSE SET @family_history = 0;
END IF;
> IF @z = ''Y''
THEN SET @family_history = 1;
ELSE SET @family_history = 0;
END IF;



,因为Knut注意到

as Knut notes


>> ;
设置x1 = @family_history;
设置x2 = @family_history;
设置x3 = @smoke;
设置x4 = 0;
设置x5 = 0;
>>
set x1 = @family_history;
set x2 = @family_history;
set x3 = @smoke;
set x4 = 0;
set x5 = 0;



SET x1 = @family_history,

x2 = @family_history,

x3 = @吸烟,

x4 = 0,

x5 = 0;


请注意,DB2表示性能可能不是最理想的。

它没有说它。


一般情况下尽量避免在SQL UDF或TRIGGERS中使用。

如果你的逻辑很复杂使用存储过程并从UDF中调用它。

请记住SQL UDF(和触发器)内联到执行中

计划。

我的经验法则是,任何不适合屏幕的逻辑东西都是属于存储过程。


干杯

Serge

-

Serge Rielau

DB2解决方案开发

IBM多伦多实验室


WAIUG会议
http://www.iiug.org/waiug/present/Fo...For um2006.html


这篇关于UDF的次优性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆