Managing SQL Performance

  • 1,264 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,264
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
143
Comments
0
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. ! ! ! ! !! ! !"#"$%#$& ()& *+,-.,/"#0+& 1.23.3&4/5.3%6/&7899& :,"%#%#$&;"4& & & & #$%&%(%)!*+! ,-$%!./$(/! !"#$%&#&(#)(%*+",-&.(!! ! ! ! "!
  • 2. ! ! ! !!! 0! ! ! ! ! ! ! ! ! ! !
  • 3. ! ! ! ! !! ! !"#"$%#$&()&*+,-.,/"#0+& 2/(&/&!3+45/&674!08""!9!:$-66;!<-+! 08""=81="8! ! ,-$%!./$(/! karen.r.morton@gmail.com http://karenmorton.blogspot.com / !"#$%&$()$*"&+$*,%&-&-.$/%0$&+$*($%1#$%-%.&-.$"(2$345$6#,)(,+$%-$#-.,%&-#/7%8*(%*&9$ 6%,*$()$0(8,$%66:&9%*&(-$:&)#909:#;$<%-%.&-.$"(2$0(8,$345$6#,)(,+$+"(8:/-=*$>#$%$?(>$%++&.-#/$ *($ (-#$ 6#,+(-$ (,$ ,(:#@$ >8*$ *"#$ ?(>$ ()$ #A#,0(-#$ &-A(:A#/$ &-$ *"#$ /#A#:(6#-*$ %-/$ (-B.(&-.$ %&-*#-%-9#$ %-/$ +866(,*$ ()$ 0(8,$ %66:&9%*&(-+;$ !((:+$ %-/$ *#9"-&C8#+$ :#%,-#/$ 2&::$ "#:6$ 0(8$ 2,&*#$>#**#,$345$)%+*#,$%-/$#-%>:#$0(8$*($C8&91:0$/&%.-(+#$6((,:0$6#,)(,&-.$345;$D(8=::$%:+($ :#%,-$ "(2$ *($ ,#9(.-&E#$ %-/$ 9(,,#9*$ %-0$ 9((-$ %-*&6%**#,-+$ *"%*$ %0$ >#$ 6,#+#-*$ &-$ 0(8,$ 98,,#-*$9(/#$*"%*$%,#$6,(>:#+$2%&*&-.$*($"%66#-;$9 <=:>?;@A:<?=& :>6&!&%?(6/!6&!%@?%$5(%)!A6(>!5%$46&&6/!B$/4!C>-5(%$!D!/B!E@5%$(!F$-?G%!#$-?(6?%&H!F$-?G%!<-(-*-&%! I)466&($-(6/!B$/4!(>%!F-J!:-*G%K!I5$%&&K!08"8L!M>-(!6&!(>%!B6$&(!(>6;!+/7!(>6J!/B!A>%!+/7!&%%!(>%!(/56?!N.--;6;!3OP!#%$B/$4-?%QR!</!+/7!(>6J!/B!$%&5/&%!(64%R!</!+/7!(>6J!/B!7&%$!?/45G-6(&!-*/7(!(>%!-55G6?-(6/!$76;!N(//!&G/AQR!</!+/7!(>6J!/B!IMS!/$!I<<.!$%5/$(&R!! I&!B-$!-&!7&%$&!-$%!?/?%$%)K!5%$B/$4-?%!is $%&5/&%!(64%L!T&%$&!)/U(!?-$%!-*/7(!&%$V%$!-)!)-(-*-&%!?/B6;7$-(6/&K!%(A/$J!*-)A6)(>K!W=F!$-(%&K!/$!X7%$+!%@%?7(6/!5G-&L!:>%+!?-$%!-*/7(!how fast(>%+!5%$?%6V%!(>%6$!-55G6?-(6/&!$7L!IGG!(>-(!/(>%$!&(7BB!6&!;%%J!&5%-J!-)!)/%&U(!%V%!*G65!/!(>%6$!$-)-$L!S%;-$)G%&&!/B!A>%(>%$!/$!/(!-GG!+/7$!4/6(/$6;!;-);%(&!BG-&>!;$%%!G6;>(&!/B!5%$B%?(6/K!6B!+/7$!7&%$&!-$%!?/45G-66;K!+/7UV%!;/(!-!5$/*G%4L!:>%!($7(>!6&K!(>%!&%%)&!/B!(>/&%!5$/*G%4&!V%$+!G6J%G+!A%$%!5G-(%)!A>%!(>%!?/)%!A-&!B6$&(!A$6((%L!9B9 CD.52%#$&"&*+,-.,/"#0+&!%#D3+2&.--;6;!(>%!5%$B/$4-?%!/B!+/7$!-55G6?-(6/!3OP!)/%&U(!&(-$(!A>%!+/7$!7&%$&!*%;6!(/!?/45G-6L!W(!&(-$(&!*%B/$%!(>%!B6$&(!&(-(%4%(!6&!%V%$!A$6((%L!W(!&(-$(&!A>%!(>%!*7&6%&&!(-&J&!(>-(!+/7$!-55G6?-(6/!A6GG!%%)!(/!&%$V6?%!-$%!)%B6%)L!F!-!(64%!G6%K!(>-(!&(-$(6;!5/6(!-)!(>%!B6$&(!7&%$!?/45G-6(!-*/7(!5%$B/$4-?%!?/7G)!*%!X76(%!B-$!-5-$(L!Y7(!W!-*&/G7(%G+!*%G6%V%!(>-(!+/7!>-V%!(/!&(-$(!*+!?/&6)%$6;!+/7$!7&%$U&!%@5%$6%?%L!! WB!+/7!&(-$(!*+!(>6J6;!/B!>/A!+/7$!7&%$!A6GG!%@5%$6%?%!+/7$!-55G6?-(6/K!(>6&!645G6%&!(>-(!4--;6;!3OP!5%$B/$4-?%!6&!B6$&(!-*/7(!-!46)&%(K!/(!-!)-(-&%(L!Z/7$!46)&%(!6&K!6!5-$(K!$%G-(%)!(/!(>%!&%(!/B!$7G%&!+/7UV%!6(%$-G6[%)L!Y7(!6(U&!-G&/!-*/7(!+/7$!*%G6%B&!-)!B%%G6;&!$%G-(%)!(/!A>-(!5%$B/$4-?%!6&!-)!4%-&L!</!+/7!(>6J!4--;6;!5%$B/$4-?%!6&!>-$)R!</!+/7!(>6J!4--;6;!5%$B/$4-?%!6&K!/$!6&U(K!+/7$!$%&5/&6*6G6(+R!</!+/7!(>6J!5%$B/$4-?%!6&!&/4%(>6;!(/!(>6J!-*/7(!G-(%$K!A>%K!/$!6BK!5$/*G%4&!-$6&%R!</!+/7!(>6J!4--;6;!5%$B/$4-?%!6&!-*/7(!-V/6)6;!?-(-&($/5>%&!/$!-*/7(!%V6&6/6;!5/&&6*6G6(6%&R!! ! ! ! 1!
  • 4. ! ! ! 3/4%(64%&!+/7$!46)&%(!6&!6BG7%?%)!*+!+/7$!]/*!)%&?$65(6/L!WB!+/7!>-V%!/(!&5%?6B6?-GG+!*%%!(-&J%)!A6(>!5%$B/$4-?%!-&!-!?/?%$K!+/7!4-+!G6J%G+!6;/$%K!/$!-(!(>%!V%$+!G%-&(!46646[%K!+/7$!$/G%!6!%&7$6;!/5(64-G!5%$B/$4-?%!/B!(>%!3OP!+/7!A$6(%L!Y7(!$%;-$)G%&&!/B!+/7$!)%B6%)!]/*!$/G%K!W!)/!*%G6%V%!(>-(!%BB%?(6V%!3OP!5%$B/$4-?%!4--;%4%(!&(-$(&!A6(>!+/7$!46)&%(L!W(U&!>/A!+/7!V6%A!+/7$!$/G%!-)!(>%!?/($6*7(6/&!+/7!4-J%!6!$%;-$)!(/!(>%!5%$B/$4-?%!/B!+/7$!?/)%!(>-(!4-J%&!(>%!)6BB%$%?%!*%(A%%!-!/5(64-GG+!5%$B/$46;!-55G6?-(6/!-)!-!5//$G+!5%$B/$46;!/%L! C/&6)%$!(>%!)%B66(6/!/B!(>%!A/$)!manageH! "L (/!>-)G%!/$!)6$%?(!A6(>!-!)%;$%%!/B!&J6GGH!-&!! a: (/!4-J%!-)!J%%5!?/45G6-(!! b: (/!($%-(!A6(>!?-$%H!>7&*-)!! c: (/!%@%$?6&%!%@%?7(6V%K!-)466&($-(6V%K!-)!&75%$V6&/$+!)6$%?(6/!/B! 0L (/!A/$J!75/!/$!($+!(/!-G(%$!B/$!-!57$5/&%! 1L (/!&7??%%)!6!-??/45G6&>6;H!?/($6V%! —.%$$6-4^M%*&(%$!FG6%! www.merriam-webster.com/dictionary/manage :>6&!)%B66(6/!6)6?-(%&!(>-(!6B!+/7!A-(!&/4%(>6;!(/!*%!4--;%-*G%K!+/7!47&(!;6V%!6(!&J6GG%)!-((%(6/!-)!%BB/$(L!3/K!B6$&(!-)!B/$%4/&(K!W!(>6J!4--;6;!5%$B/$4-?%!6&!-*/7(!6(%;$-(6;!/%!&645G%!5$6?65G%!6(/!+/7$!46)&%(H!I am responsible for the performance of the code I write or maintainL!M6(>/7(!-!?/&?6/7&!5%$&/-G!?>/6?%!(/!-??%5(!$%&5/&6*6G6(+!B/$!6(K!5%$B/$4-?%!A6GG!not *%!4--;%-*G%L!! :/!4--;%!5%$B/$4-?%K!+/7!B6$&(!%%)!(/!J/A!>/A!-)!A>+!F$-?G%!)%(%$46%&!(>%!5G-!/5%$-(6/&!B/$!%-?>!X7%$+L!:>%!+/7!%%)!(/!*%!-*G%!(/!%-&6G+!-)!-??7$-(%G+!?-5(7$%!)6-;/&(6?&!6)6?-(6;!A>-(!+/7$!-55G6?-(6/!?/)%!6&!)/6;!-&!6(!%@%?7(%&L!:>-(!4%-&!G%-$6;!>/A!F$-?G%U&!?/&(^*-&%)!/5(646[%$!A/$J&K!5-$(6?7G-$G+!>/A!6(!7(6G6[%&!&(-(6&(6?&L!I)!6(!4%-&!7)%$&(-)6;!(>%!645/$(-?%!/B!>-V6;!+/7$!-55G6?-(6/!A%GG!6&($74%(%)L!! :>%!&(-(6&(6?&!7&%)!*+!(>%!/5(646[%$!-$%!G6J%!B7%G!B/$!+/7$!?-$L!:>%!X7-G6(+!/B!(>%!B7%G!+/7!57(!6(/!+/7$!V%>6?G%!-BB%?(&!>/A!A%GG!+/7$!?-$!>-)G%&K!>/A!47?>!;-&!46G%-;%!6(!;%(&K!>/A!/B(%!6(!%%)&!4-6(%-?%K!-)!%V%!>/A!G/;!+/7$!V%>6?G%!A6GG!*%!&%$V6?%-*G%L!T)%$&(-)6;!A>-(!;/%&!6!(/!(>%!/5(646[%$!&/!(>-(!6(!?-!?>//&%!A>6?>!3OP!%@%?7(6/!5G-!/5%$-(6/&!-$%!*%&(!>%G5&!+/7!J/A!A>-(!&>/7G)!$%-&/-*G+!*%!%@5%?(%)!(/!/??7$L!I)!6B!+/7!)/U(!;%(!(>%!$%&7G(&!+/7!%@5%?(!/$!;%(!(>%!5%$B/$4-?%!+/7!%%)K!+/7!?-!-)]7&(!(>%!B7%GL!! IB(%$!+/7!7)%$&(-)!A>-(!;/%&!6!(/!(>%!/5(646[%$!&/!6(!?-!4-J%!(>%!*%&(!5G-!?>/6?%&K!+/7!(>%!%%)!(/!*%!-*G%!(/!?-5(7$%!)6-;/&(6?&!X76?JG+!-)!-??7$-(%G+L!:>%$%!-$%!4-+!A-+&!(/!?-5(7$%!)6-;/&(6?!)-(-K!*7(!4--;6;!5%$B/$4-?%!A%GG!$%X76$%&!(>-(!+/7!*%!-*G%!(/!%-&6G+!?/GG%?(!(>%!4%($6?&!+/7!%%)K!A>%!+/7!%%)!(>%4L!:>%!*%&(!A-+!(/!)/!(>6&!6&!(/!5$/5%$G+!6&($74%(!+/7$!?/)%L!Instrumentation 6&!]7&(!-!B%A!%@($-!G6%&!/B!?/)%!+/7!-))!(/!+/7$!-55G6?-(6/!(/!%-*G%!+/7!(/!6)%(6B+!(>%!(-&J&!6(!%@%?7(%&!_(>-(!6&K!3OP!$%G-(%)!(/!*7&6%&&!(-&J&`!&/!(>%+!-$%!%-&+!(/!B6)!-)!4/6(/$L! 2/5%B7GG+K!WUV%!%&(-*G6&>%)!&/!B-$!(>-(!4--;6;!3OP!5%$B/$4-?%!&(-$(&!A6(>!-!-((6(7)%K!-!46)&%(L!Z/7!-??%5(!$%&5/&6*6G6(+!B/$!(>%!5%$B/$4-?%!/B!%V%$+!&(-(%4%(!+/7!A$6(%!/$!4-6(-6L!Z/7!*76G)!B/7)-(6/!J/AG%);%!-*/7(!>/A!(>%!/5(646[%$!A/$J&!-)!7&%!(>-(!J/AG%);%!(/!B%%)!(>%!/5(646[%$!A6(>!X7-G6(+!&(-(6&(6?&!-)!X7-G6(+!?/)%L!Z/7!4-J%!+/7$!-55G6?-(6/!%-&+!(/!4/6(/$!*+!-))6;!6&($74%(-(6/!(>-(!A6GG!>%G5!!! ! ! ! ! ! ! ! ! ! ! !
  • 5. ! ! ! ! !! !+/7!;%(!(>%!$6;>(!5%$B/$4-?%!4%($6?&!A>%!+/7!%%)!(>%4L!:>%!*/((/4!G6%!6&!(>-(!+/7$!46)&%(!6&!;%-$%)!(/A-$)!4--;6;!5%$B/$4-?%!%V%$+!)-+!-)!/(!]7&(!A>%!5$/*G%4&!-$6&%L! :>%!%(6$%!?>-5(%$!>-&!*%%!$%5$6(%)!-)!6?G7)%)!-(!(>%!%)!/B!(>6&!)/?74%(!B/$!+/7$!$%B%$%?%L!7 !C=CE<=E&()&*F>G?>!C=AF&.--;6;!3OP!5%$B/$4-?%!6&!B6$&(!-*/7(!-!46)&%(K!/(!-!)-(-&%(L!! !! !S%5%-(!-B(%$!4%H!!! W!-4!$%&5/&6*G%!B/$!(>%!5%$B/$4-?%!/B!(>%!?/)%!W!A$6(%!/$!4-6(-6L!7B9 :H+&E,+"2&;%I%D+&:>%$%!6&!-!)6V6)%!(>-(!6&!/B(%!B-?6G6(-(%)K!J/A6;G+!/$!7J/A6;G+K!*+!4/&(!?/45-6%&L!:>6&!6&!(>%!)6V6)%!*%(A%%!(>%!<-(-*-&%!I)466&($-(/$&!-)!(>%!<%V%G/5%$&L!M>6G%!(>%!(A/!;$/75&!%)!;/-G!4-+!*%!(/!5$/V6)%!(>%6$!?7&(/4%$&!A6(>!-!&(-*G%!-)!%BB6?6%(!-55G6?-(6/K!(>%6$!5%$&5%?(6V%&!-)!5%$?%6V%)!%%)&!(/!-?>6%V6;!(>%!%)!;/-G!6&!/B(%!$-)6?-GG+!)6BB%$%(L!:>6&!)6V6)%!?-!?-7&%!B$6?(6/!*%(A%%!(>%!(A/!;$/75&!-)!-G&/!4-J%!6(!%-&+!B/$!%-?>!;$/75!(/!5/6(!(/!(>%!/(>%$!A>%!5%$B/$4-?%!6&&7%&!-$6&%L!! ! ! ! a!
  • 6. ! ! !! ! <%V%G/5%$&!4-+!(-J%!(>%!-((6(7)%!(>-(!(>%6$!]/*!6&!(/!5$/)7?%!-55G6?-(6/&!$6?>!A6(>!B%-(7$%&!7&%$&!A-(!-)!)%4-)L!:>%!)-(-*-&%!6&!&645G+!-!*G-?J!*/@!(>%+!47&(!6(%$-?(!A6(>!6!/$)%$!(/!;%(!(>%!)-(-L!2/A!(>%+!;/!-*/7(!;%((6;!(>-(!)-(-K!-)!(>%!5%$B/$4-?%!645G6?-(6/&!/B!(>%6$!4%(>/)&K!4-+!/(!%V%!*%!5-$(!/B!(>%!%X7-(6/!-&!(>%+!$7&>!(/!5$/V6)%!$-56)!)%5G/+4%(!/B!B7?(6/&!-)!B%-(7$%&L! <YI&!/B(%!A6GG!/B(%!B-?6G6(-(%!(>%!)%V%G/5%$U&!*G-?J!*/@!4%(-G6(+!*+!G646(6;!-??%&&!(/!/*]%?(&!-)!)-(-!%%)%)!(/!5$/5%$G+!$%V6%AK!(%&(!-)!V%$6B+!3OP!5%$B/$4-?%L!:>6&!4-+!?/4%!B$/4!(>%!B%-$!/B!G/&6;!?/($/G!/B!(>%!%V6$/4%(!*+!/5%6;!75!-??%&&!(/!%G%4%(&!(>%+!?/&6)%$!(/!*%!*%+/)!(>%!7)%$&(-)6;!/B!/^<YI&L!:>%!<YI!4-+!*%!-*G%!(/!B6)!N*-)Q!3OP!-)!J6?J!6(!*-?J!(/!(>%!)%V%G/54%(!(%-4K!*7(!(>%!)%V%G/5%$&!-$%!>-4&($7;!(/!)/!-+(>6;!%@?%5(!;7%&&!-(!A>-(!645$/V%4%(&!4-+!>%G5!&6?%!(>%+!)/U(!>-V%!-??%&&!(/!A>-(!(>%+!%%)L!7B7 E%I+&J+/&KH"2&2H+4&#++DL&S%;-$)G%&&!/B!(>%6$!$/G%K!;6V6;!%-?>!5%$&/K!A>-(!(>%+!%%)!(/!4-J%!5%$B/$4-?%!--G+&6&!-!5-$(!/B!(>%6$!)-+^(/^)-+!-?(6V6(6%&!6&!?$6(6?-G!(/!4--;6;!3OP!5%$B/$4-?%!?/&6&(%(G+L!M>-(!6&!%%)%)!6&!$%-GG+!X76(%!&645G%L!b7&(!*%?-7&%!(>%!%%)&!-$%!&645G%!)/%&U(!4%-!(>%+!-$%!4%(L!7B7B9 :,"%#%#$&:$-66;!6&!/%!/B!(>%!4/&(!645/$(-(!%%)&!(>-(!47&(!*%!4%(L!:>%$%!-$%!(A/!4-6!>6)$-?%&!(/!;%((6;!%V%$+/%!(>%!($-66;!(>%+!%%)H!(64%!-)!4/%+L!:>%!/$4-G!)-+^(/^)-+!)%4-)&!/B!?/45G%(6;!$%X76$%)!(-&J&!?-!G%-V%!G6((G%!(64%!B/$!($-66;L!:-J6;!(64%!-A-+!B$/4!(>%!/BB6?%!B/$!($-66;!$%X76$%&!(>-(!)-+^(/^)-+!(-&J&!-)!$%&5/&6*6G6(6%&!%6(>%$!B-GG!/!&/4%/%!%G&%K!/$!;%(!5/&(5/%)!7(6G!(>%!5%$&/!$%(7$&!(/!(>%!/BB6?%L!I)K!A6(>!*7);%(&!*%6;!(6;>(G+!4--;%)K!4/6%&!B/$!($-66;!&%%4!(/!*%!/%!/B!(>%!B6$&(!(>6;&!(/!;%(!?7(!A>%!?/&(^&-V6;&!-$%!%%)%)L!! 3/K!>/A!)/!+/7!-?X76$%!(>%!&J6GG&!%%)%)!B/$!+/7!-)!+/7$!(%-4&!6B!*/(>!(64%!-)!4/%+!-$%!B-?(/$&R!M%GGK!WUGG!B-GG!*-?J!/!(>%!/G)!-)-;%!NA>%$%!(>%$%U&!-!A6GG!(>%$%U&!-!A-+LQ!:A/!/5(6/&!?/4%!644%)6-(%G+!(/!46)!B/$!($-66;!(>-(!?-!*%!6%@5%&6V%!6!(%$4&!/B!*/(>!(64%!-)!4/%+!&5%(L! • Y$/A!*-;!G7?>%&! • P6V%=%(!4%%(6;!!! D! ! ! ! ! ! ! ! ! ! !
  • 7. ! ! ! ! !! ! :-J6;!-!>/7$!/V%$!G7?>!(/!?/)7?(!*$/A!*-;!&%&&6/&!?-!5$/V6)%!-!A-+!B/$!?/^A/$J%$&!(/!*76G)!(>%6$!J/AG%);%!-)!&J6GG!G%V%G&!A6(>/7(!(-J6;!G-$;%!?>7J&!/B!(64%!-A-+!B$/4!(>%!/$4-G!$/7(6%L!:>%&%!&%&&6/&!?-!*%!?/)7?(%)!*+!(%-4!4%4*%$&!A>/!$/(-(%!(-J6;!/!(>%!$/G%!/B!($-6%$L!E-?>!5%$&/!?-!&(-$(!*+!?/)7?(6;!/%!/$!4/$%!&%&&6/&!?/V%$6;!&J6GG&!B/$!A>6?>!(>%+!-$%!-G$%-)+!5$/B6?6%(L!F(>%$!&J6GG&!(>-(!%%)!(/!*%!-))%)!(/!(>%!;$/75!?-!*%!&5G6(!75!-4/;!(>%!(%-4!4%4*%$&!-)!%-?>!5%$&/!?-!$%&%-$?>K!&(7)+!-)!5$%5-$%!4-(%$6-G&!(/!(>%!&>-$%!A6(>!(>%!;$/75L! I/(>%$!*$/A!*-;!/5(6/!?/7G)!*%!(/!G/?-(%!($-66;!-V-6G-*G%!B$/4!(>%!6(%$%(!-)!&?>%)7G%!-!G7?>!&%&&6/!B/$!(>%!(%-4!(/!4%%(!6!/%!?/B%$%?%!$//4!-)!5$/]%?(!(>%!($-66;!B/$!(>%!A>/G%!;$/75L!F$K!4-J%!-$$-;%4%(&!B/$!-!&%$6%&!/B!&%&&6/&!A6(>!G/?-G!_/$!$%4/(%`!%@5%$(&!A>/U)!*%!A6GG6;!(/!A/$J!A6(>!+/7!(/!)%V%G/5!&>/$(!&5%?6B6?!&%;4%(&!B/$!]7&(!(>6&!57$5/&%L!E;-;6;!/7(&6)%!V%)/$&!4-+!4%-!+/7!&5%)!-!G6((G%!4/%+K!*7(!(>6J!/7(&6)%!(>%!*/@!-!*6(!/!A>-(!6&!5/&&6*G%!-)!+/7!%V%$!J/A!A>-(!+/7!4-+!*%!-*G%!(/!A/$J!/7(L! WB!+/7$!(%-4!6&!/(!-GG!G/?-(%)!6!(>%!&-4%!/BB6?%K!+/7!4-+!%%)!(/!)/!(>%&%!J6)&!/B!&%&&6/&!7&6;!P6V%!.%%(6;K!d/:/.%%(6;!/$!A>-(%V%$!/(>%$!$%4/(%!4%%(6;!&%$V6?%!+/7!-$%!B-46G6-$!A6(>L!W!;%%$-GK!(>%!7&%!/B!(>%&%!(+5%&!/B!&%$V6?%&!(>-(!-GG/A!+/7!(/!-GG/A!/(>%$&!(/!V6%A!+/7$!&?$%%!4-J%&!6(!47?>!%-&6%$!(/!A/$J!6!&>/$(!($-66;!&%&&6/&!A6(>!;$%-(%$!%-&%L!7B7B7 A.//6#%0"2%.#&I&!A%!>-V%!-G$%-)+!)6&?7&&%)K!(>%$%!6&!/B(%!-!)6V6)%!*%(A%%!<YI&!-)!)%V%G/5%$&!?-7&%)K!6!5-$(K!*+!(>%6$!)6BB%$%(!5%$&5%?(6V%&L!M>%$%!(>%&%!)6BB%$%?%&!*%?/4%!-55-$%(!6&!6!(>%!A-+!(>%!;$/75&!?/4476?-(%K!/$!5%$>-5&!6(!A/7G)!*%!*%((%$!&(-(%)!(/!&-+!6!(>%!A-+!(>%!;$/75&!)/U(!?/4476?-(%L!! 36?%!(>%!5$64-$+!B/?7&!/B!%-?>!;$/75!6&!/B(%!X76(%!)6BB%$%(K!(>%!G-;7-;%!7&%)!-)!(>%!G%V%G!/B!7)%$&(-)6;!%-?>!;$/75!>-&!/B!(>%!/(>%$!?-!*%?/4%!5-$(!/B!(>%!5$/*G%4!6!;%((6;!5%$B/$4-?%!5$/*G%4&!>-)G%)!6!-!(64%G+!B-&>6/L!WUV%!&%%!-!5$/*G%4!;%(!*/7?%)!*-?J!-)!B/$(>!*%(A%%!;$/75&!6!%4-6G!?>-6&!(>-(!$7!a8!(>$%-)&!)%%5L!Y+!(>%!(64%K!%V%$+/%!>-&!A-)%)!(>$/7;>!(>%!%(6$%!%@?>-;%K!(>%!/$6;6-G!5$/*G%4!/B(%!;%(&!G/&(L! !! WUV%!/B(%!A/)%$%)!A>%!6(!A-&!(>-(!B-?%^(/^B-?%!?/V%$&-(6/&!/$!5>/%!?-GG&!*%?-4%!&/4%(>6;!(/!-V/6)!-&!47?>!-&!+/7!A/7G)!(>%!5G-;7%L!#%$>-5&!6(!>-&!&/4%(>6;!(/!)/!A6(>!%V%$+/%!A-(6;!(/!>-V%!?/4476?-(6/&!)/?74%(%)!&/!(>-(!(>%+!?-!>-V%!-!($-6G!/B!?/V%$&-(6/!(>%+!?-!5/6(!*-?J!(/!G-(%$L!Y7(K!W!(>6J!(>%!)6V6)%!*%(A%%!;$/75&!6&!6?$%-&%)!*+!G-?J!/B!5%$&/-GK!G6V%!?/(-?(L!:>%$%!>-V%!*%%!(64%&!A>%!WUV%!]7&(!A-GJ%)!)/A!(>%!>-GG!(/!&/4%/%U&!-)!A-&!-*G%!(/!7&%!-!A>6(%*/-$)!-)!(-J%!"8!467(%&!(/!(-GJ!! ! ! ! c!
  • 8. ! ! !-*/7(!(>%!6&&7%!-)!6(!A-&!>-)G%)L!:>%!-G(%$-(6V%!6&!4/&(!/B(%!&5%)6;!>-GB!(>%!)-+!&%)6;!%4-6G!*-?J!-)!B/$(>!A6(>!/!&/G7(6/!-)!B$7&($-(6/!G%V%G&!6?$%-&6;!-&!(64%!BG6%&!*+L!! E4-6G!?-!*%!X76(%!(%$&%!-)!/B(%!6(!6&!V6$(7-GG+!645/&&6*G%!(/!5$/5%$G+!6]%?(!%4/(6/!6!(%@(!B/$4L!:-J%!(>6&!&6(7-(6/!B/$!%@-45G%H!W!A-&!/!(>%!)6&($6*7(6/!/B!-!%4-6G!(>-(!?/(-6%)!-!B%A!5-$-;$-5>&!%@5G-66;!&/4%(>6;!-)!-&J%)!/%!/$!(A/!X7%&(6/&!(/!A>6?>!(>%!&%)%$!%%)%)!-!$%&5/&%L!W!)6)U(!6B%$!-+!(/%!/$!%4/(6/!6!6(!A>%!W!$%-)!6(!*7(!-/(>%$!5%$&/!&%(!*-?J!-!$%5G+!&-+6;K!N:/7?>+K!(/7?>+L!M>%!A%!-GG!?-G4!)/A!4-+*%!A%UGG!;%(!(/!(>%!-&A%$&LQ!27>R!I!4%%(6;!A-&!?-GG%)!B/$!(>%!%@(!4/$6;!(/!)6&?7&&!(>%!6&&7%!-)!(>6;&!A%$%!(-J%!?-$%!/B!6!]7&(!-!B%A!467(%&!A6(>!/!/%!46&6(%$5$%(6;!A>-(!A-&!*%6;!&-6)L!WB!(>%!4%%(6;!>-)!*%%!?-GG%)!66(6-GG+K!(>%!6&&7%!?/7G)!>-V%!*%%!>-)G%)!A6(>6!467(%&!6&(%-)!/B!%@(%)6;!(/!-!&%?/)!)-+L!! W!J/A!A%U$%!-GG!*7&+!-)!%4-6G!6&!/B(%!-!A-+!(/!X76?JG+!$%&5/)K!*7(!WU)!&7;;%&(!(>-(!%4-6G!?/7G)!/B(%!*%!7&%)!(/!?/B6$4!-)!B/$4-G6[%!6^5%$&/!/$!5>/%!?/V%$&-(6/&!-)!(/!5$/V6)%!(>%!)/?74%(-(6/!($-6GL!WUV%!;/((%!6(/!(>%!>-*6(!/B!/G+!?>%?J6;!4+!%4-6G!/?%!%V%$+!>/7$!/$!(A/!)%5%)6;!/!A>-(!WU4!A/$J6;!/!&/!-&!(/!/(!&5%)!-GG!4+!(64%!(>%$%L!I)K!A>-(!WUV%!-?(7-GG+!*%%!;G-)!(/!&%%!6&!(>-(!6B!&/4%/%!&%)&!/7(!-!%4-6G!(>-(!(>%+!A-(!4%!(/!-&A%$!6!0!467(%&K!-)!W!)/U(K!(>%+UGG!(+56?-GG+!56?J!75!(>%!5>/%!-)!?-GG!4%L!W!(>6J!WU4!/!(/!&/4%(>6;f!7B7BM C00+33&2-V6;!(>%!5$6V6G%;%&!(/!-??%&&!(>%!%?%&&-$+!/*]%?(&!-)!&755G6%)!5-?J-;%&!(>-(!5$/V6)%!5%$B/$4-?%!)-(-!6&!-!?$6(6?-G!%%)!(>-(!W!&%%!)%6%)!(/!)%V%G/5%$&!-;-6!-)!-;-6L!M>6G%!W!?%$(-6G+!7)%$&(-)!(>%!%%)!(/!G646(!-??%&&!6!5$/)7?(6/!-)!J%+!5$%^5$/)7?(6/!%V6$/4%(&K!6(!6&!V%$+!)6BB6?7G(!B/$!4%!(/!7)%$&(-)!(>%!]7&(6B6?-(6/!B/$!5$/>6*6(6;!-??%&&!6!(>%!)%V%G/54%(!-)!(%&(6;!%V6$/4%(&L!WUV%!>%-$)!-GG!(>%!-$;74%(&!B/$!A>+!-??%&&!6&!/B(%!G646(%)K!*7(!6B!A%!?-!-;$%%!(>-(!5%$B/$4-?%!6&!%V%$+/%U&!$%&5/&6*6G6(+K!V6$(7-GG+!-GG!(>%!-$;74%(&!(/!5$/>6*6(=G646(!-??%&&!;/!/7(!(>%!)//$L! I??%&&!(/!(>%!%-?>!/B!(>%!B/GG/A6;!6&!?$6(6?-GH!! • )+-46?!5%$B/$4-?%!_gh`!V6%A&!_G6J%!gh3E33WFiK!gh3OPj#PIiK!%(?L`! • %@(%)%)!3OP!($-?%!)-(-!_-??%&&!(/!T3ESj<T.#j<E3:`! • &755G6%)!5-?J-;%&!_G6J%!<Y.3j.FiW:FSK!<Y.3jT:WPW:ZK!%(?L`! :>%!4/$%!-??%&&!(/!(>%&%!/*]%?(&!6&!G646(%)K!(>%!G%&&!%BB%?(6V%!-!5%$&/!?-!*%!A>%!-((%45(6;!(/!$%V6%A!-)!/5(646[%!5%$B/$4-?%L!k/$!%@-45G%K!G%(U&!&-+!-!J%+!*7&6%&&!7&%$!?-GG%)!(>%!>%G5!)%&J!A6(>!-!?/45G-6(!-*/7(!(>%!5%$B/$4-?%!/B!(>%!NC7&(/4%$!3%-$?>Q!&?$%%L!:>%!5$/*G%4!6&!$%5/$(%)!B6$&(!(/!(>%!<YI!_A>/K!6B!+/7!!$%4%4*%$!B$/4!/7$!%-$G6%$!)6&?7&&6/`!)/%&U(!J/A!-+(>6;!47?>!-*/7(!(>%!-55G6?-(6/L!:>%!<YI!;/%&!/7(!(/!;$-*!-!IMS!/$!I32!$%5/$(!B/$!(>%!(64%!5%$6/)!)7$6;!A>6?>!(>%!?/45G-6(!A-&!B6G%)L!F!(>-(!$%5/$(K!(>%+!&%%!-!?/75G%!/B!3OP!&(-(%4%(&!(>-(!&>/A!75!-(!(>%!(/5!/B!(>%!G6&(!B/$!%G-5&%)!(64%L!:>%+!?/5+!(>%!3OP!&(-(%4%(!-)!&%)!6(!(/!(>%!)%V%G/54%(!(%-4!A6(>!-!/(%!&-+6;K!N#G%-&%!4-J%!(>6&!$7!B-&(%$LQ!:>%!)%V%G/5%$!A>/!;%(&!(>%!3OP!%@%?7(%&!6(!6!(>%6$!(%&(!%V6$/4%(!-)!&-+&K!NW(!A/$J&!B6%!A>%!W!$7!6(LQ!FB!?/7$&%K!&6?%!(>%!)%V%G/5%$!)/%&U(!>-V%!-??%&&!(/!-+(>6;!(/!*%!-*G%!(/!)/!-!4/$%!(>/$/7;>!--G+&6&K!(>-(U&!-*/7(!-GG!(>%+!?-!)/!B/$!/AL!:>%!<YI!&>$7;&!-)!(>6J&!6(!47&(UV%!*%%!-!N;G6(?>Q!-)!B/$;%(&!-*/7(!6(L!! I!G6((G%!A>6G%!G-(%$K!(>%!7&%$!?-GG&!6!-;-6!A6(>!4/$%!?/45G-6(&!&/!(>%!<YI!;/%&!-!&(%5!B7$(>%$!-)!;$-*&!(>%!%@%?7(6/!5G-!B$/4!IMS!B/$!(>6&!5-$(6?7G-$!3OP!-)!&%)&!(>-(!*-?J!(/!(>%!)%V%G/5%$!&-+6;K!N:>%$%U&!;/(!(/!*%!-!5$/*G%4!-&!(>%!7&%$!6&!&(6GG!?/45G-66;L!:-J%!-!G//J!-(!(>6&!5G-l!6(!G//J&!0"1L!WU4!&7$%!+/7UGG!*%!-*G%!(/!B6@!6(!/?%!+/7!(-J%!-!G//J!-(!(>6&LQ!:>%!)%V%G/5%$!G//J&!-(!(>%!5G-!-)!)/%&U(!&%%!-+!B7GG!(-*G%!&?-&!-)!(>%!!! e! ! ! ! ! ! ! ! ! ! !
  • 9. ! ! ! ! !! !?/&(!&>/A!6&!/G+!"8L!3?$-(?>6;!>6&!>%-)K!>%!?-GG&!(>%!<YI!-)!&-+&K!NW(U&!]7&(!/(!-!5$/*G%4!A6(>!(>%!3OPL!:>-(!5G-!G//J&!+((1!(/!4%L!W(!47&(!*%!-!)-(-*-&%!5$/*G%4LQ!:>%!<YIK!A>/!-*&/G7(%G+!!%(23!>6&!)-(-*-&%!6&!]7&(!B6%!;$74*G%&!-*/7(!(>%!)%V%G/5%$&!-)!&(-$(&!($+6;!(/!B6;7$%!/7(!(>%!5$/*G%4!>64&%GBL! W!?/7G)!;/!/!G6J%!(>6&!-)!-7&%74K!*7(!WUGG!&5-$%!+/7!(>%!(%)674L!:>%!B-?(!6&!(>-(!6!&/4%!&>/5&!(>6&!/??7$&!X76(%!B$%X7%(G+L!C/45G-6(&!-*/7(!5//$G+!5%$B/$46;!3OP!(7$!6(/!-!56;^5/;!4-(?>!*%(A%%!(>%!<YI&!-)!)%V%G/5%$&!A6(>!/!/%!4-J6;!-+!5$/;$%&&L!.7?>!/B!(>6&!A-&(%)!%BB/$(!?/7G)!*%!-V/6)%)!6B!%V%$+/%!>-)!-??%&&!(/!A>-(!(>%+!%%)!-)!?/7G)!A/$J!(>%!5$/*G%4!-&!-!(%-4!6&(%-)!/B!*/7?6;!(>%!5$/*G%4!*-?J!-)!B/$(>!A6(>!/!$%-G!5$/;$%&&L! W!(>%!%)K!(>%!J%+!6&!(/!4-J%!6(!-&!&645G%!-)!%-&+!-&!5/&&6*G%!(/!;%(!(>%!)-(-!%%)%)!(/!X76?JG+!--G+[%!-)!?/$$%?(!-!3OP!5%$B/$4-?%!5$/*G%4L!F%!A-+!(/!4-J%!6(!%-&+!6&!(/!-$4!%V%$+/%!A6(>!(>%!(//G&!(>%+!%%)!(/!;%(!(>%!6B/$4-(6/!(>%+!%%)L!:>%!(//G&!?-!*%!&?$65(&!/$!-!G6*$-$+!/B!?/44/G+!7&%)!X7%$6%&!/$!-!57$?>-&%)!5$/)7?(L!W!>-V%!-!&%(!/B!&?$65(&!-)!X7%$6%&!(>-(!W!7&%!(/!>%G5!?/GG%?(!%V%$+(>6;!W!(+56?-GG+!%%)L!W!-G&/!>-V%!-!B%A!;$%-(!(//G&!G6J%!(>%!2/(&/&!#$/B6G%$!_-)!$%G-(%)!3OP!<%V%G/5%$!%@(%&6/`L!.%(>/)!S!-G&/!>-&!-!;$%-(!&%(!/B!(//G&K!-4%)!.S://G&!-)!.S:$-?%K!&5%?6B6?-GG+!?$%-(%)!(/!>%G5!+/7!A/$J!A6(>!%@(%)%)!3OP!($-?%!B6G%&L!7B7BMB9 A"3+&26D4&I!&645G%!&?$65(!(>-(!%@%?7(%&!%-?>!6;>(!-)!6&&7%&!-!74*%$!/B!T#<I:E!&(-(%4%(&!A%(!B$/4!(-J6;!-55$/@64-(%G+!a!467(%&!(/!a!467(%&!*%(A%%!)-6G+!%@%?7(6/&L!:>6&!&?$65(!47&(!B66&>!*%B/$%!/(>%$!]/*&!&(-$(!6!/$)%$!(/!4-J%!&7$%!(>%!5$/?%&&%&!(>-(!B/GG/A!5$/5%$G+!>-)G%!$%4/V6;!7*6GG%)!%@?%5(6/&!B/$!?7&(/4%$!)-(-!6!(>%!&(-(%&!/B!i%A!Z/$JK!:%@-&!-)!i%A!.%@6?/L!:>%!&?$65(!A-&!645G%4%(%)!-&!-!A/$J^-$/7)!B/$!-!-55G6?-(6/!*7;!-)!A6GG!$7!6;>(G+!7(6G!(>%!%%)%)!B6@%&!?-!*%!4-)%!(/!(>%!-55G6?-(6/L! E-?>!6;>(!A>%!(>%!&?$65(!?/45G%(%&K!-!/(6B6?-(6/!%4-6G!6&!&%(!(/!(>%!-55$/5$6-(%!&755/$(!(%-4&L!k/$!(>%!6;>(!(>%!]/*!%@%?7(6/!(64%!6?$%-&%)K!(>%!%@%?7(6/!(64%!A-&!/(%)!6!(>%!%4-6G!-)!-!>6;>!5$6/$6(+!5$/*G%4!(6?J%(!A-&!?$%-(%)!(/!--G+[%K!)6-;/&%!-)!?/$$%?(!(>%!6&&7%L!:>%!)%V%G/54%(!(%-4!A-&!/(6B6%)!-)!$%X7%&(%)!(>%!<YI!(%-4!(/!>%G5!A6(>!(>%!$//(!?-7&%!--G+&6&L! W!$%V6%A%)!(>%!&?$65(!-)!B/7)!(>-(!6(!6?G7)%)!0aD!6)6V6)7-G!T#<I:E!&(-(%4%(&!G6J%!(>6&H! UPDATE TR_POLICY set POL_TYPE_CD = 1, audit_rec_updt_dts = SYSTIMESTAMP, audit_rec_updt_ver_nbr = audit_rec_updt_ver_nbr + 1, audit_rec_updt_appl_id = DCCR WHERE REPORTED_PROP_STATE_CD = NY AND RATE_POLICY_CD = 111 AND DECODE("POL_SUB_STAT_CD", UBE, 1, VALID, 2, EXCEPTION, 2, 0) = 1 AND POL_DATA_SOURCE_CD = UPLOAD;E-?>!T#<I:E!V-$6%)!/G+!*+!(>%!V-G7%!(/!*%!&%(!B/$!#FPj:Z#EjC<!-)!(>%!5$%)6?-(%!V-G7%&!B/$!SE#FS:E<j#SF#j3:I:EjC<!-)!SI:Ej#FPWCZjC<L!! W!;$-**%)!(>%!%@%?7(6/!)-(-!B$/4!IMS!_7&6;!(>%!&(-)-$)!-A$$5(L&XG`!-)!B/7)!(>-(K!/!-V%$-;%K!%-?>!6)6V6)7-G!T#<I:E!(//J!-55$/@64-(%G+!"8^""!&%?/)&!(/!?/45G%(%L!d6V%!(>-(!(>%!7&7-G!(64%!B/$!-!&6;G%!%@%?7(6/!(/!?/45G%(%!(//J!-$/7)!-!&%?/)K!W!&7&5%?(%)!(>%!5$/*G%4!A-&!A6(>!&(-(6&(6?&!(>-(!4-+!>-V%!?-7&%)!(>%!%@%?7(6/!5G-!(/!?>-;%!B/$!(>%!A/$&%L! W!(//J!(>%!3OPjW<!B$/4!(>%!$%5/$(!-)!X7%$6%)!IMS!7&6;!-!&?$65(!-4%)!@5)-A$L&XG!(/!$%($6%V%!(>%!%@%?7(6/!5G-!B/$!/%!/B!(>%!T#<I:E&!)7$6;!(>%!N&G/AQ!(64%L!W!-G&/!57GG%)!-!%@%?7(6/!5G-!B/$!(>%!&-4%!3OPjW<!B$/4!-!5$6/$!%V%6;!A>%!6(!>-)!?/45G%(%)!6!(>%!7&7-G!0!467(%!A6)/AL!:>%!(A/!5G-&!A%$%!X76(%!)6BB%$%(L!2%$%U&!(>%!*-&6?!N*-)Q!5G-!B/GG/A%)!*+!(>%!N;//)Q!5G-H!! ! ! ! m!
  • 10. ! ! !Y-)!5G-! ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 1472 | | 287K (3)| |* 1 | TABLE ACCESS BY INDEX ROWID | TR_POLICY | 4 | 1472 | | 287K (3)| | 2 | BITMAP CONVERSION TO ROWIDS | | | | | | | 3 | BITMAP AND | | | | | | | 4 | BITMAP CONVERSION FROM ROWIDS| | | | | | | 5 | SORT ORDER BY | | | | 37M| | |* 6 | INDEX RANGE SCAN | TR_POLICY_N5 | | | | 6543 (1)| | 7 | BITMAP CONVERSION FROM ROWIDS| | | | | | | 8 | SORT ORDER BY | | | | 95M| | |* 9 | INDEX RANGE SCAN | TR_COUNTY_FK6 | | | | 8721 (1)| ---------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("RATE_POLICY_CD"=111 AND "POL_DATA_SOURCE_CD"=UPLOAD) 6 - access(DECODE("POL_SUB_STAT_CD",UBE,1,VALID,2,EXCEPTION,2,0)=1) filter(DECODE("POL_SUB_STAT_CD",UBE,1,VALID,2,EXCEPTION,2,0)=1) 9 - access("REPORTED_PROP_STATE_CD"=NY) filter("REPORTED_PROP_STATE_CD"=NY)!d//)!5G-! ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes| Cost (%CPU)| ---------------------------------------------------------------------------------- |* 1 | TABLE ACCESS BY INDEX ROWID| TR_POLICY | 1 | 368 | 7307 (1)| |* 2 | INDEX RANGE SCAN | TR_POLICY_N5 | 16711 | | 92 (0)| ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(("RATE_POLICY_CD"=111 AND "POL_DATA_SOURCE_CD"=AND "REPORTED_PROP_STATE_CD"=NY)) 2 - access("TR_POLICY"."SYS_NC00063$"=1)! M6(>!]7&(!(>6&!5G-!)-(-K!(>%!&(-(6&(6?&!-$%!)%B66(%G+!G//J6;!G6J%!(>%!?7G5$6(L!W!(>%!;//)!5G-K!(>%!6)%@!$-;%!&?-!/!:Sj#FPWCZjia!>-&!-!?/&(!/B!m0!-)!%&(64-(%)!/G+!"DKc""!$/A&!(/!*%!$%(7$%)L!Y7(!6!(>%!*-)!5G-K!(>%!&-4%!&?-!?/&(&!Da1!-)!%&(64-(%)!(>-(!1c!46GG6/!$/A&!A/7G)!*%!$%(7$%)L!W(!&%%4&!6(U&!(64%!(/!?>%?J!(>%!&(-(6&(6?&L!Y%?-7&%!/7$!&(-(6&(6?&!?/GG%?(6/!6&!6&($74%(%)K!W!?-!%-&6G+!?>%?J!(/!&%%!A>%!&(-(6&(6?&!A%$%!G-&(!?/GG%?(%)!B/$!-!5-$(6?7G-$!/*]%?(L!M%UGG!(-GJ!4/$%!-*/7(!6&($74%(-(6/!&>/$(G+K!&/!WUGG!/(!;/!6(/!4/$%!)%(-6G!/!(>-(!/AL!I!X76?J!?>%?J!&>/A%)!4%!(>-(!(>%!(-*G%!*%6;!75)-(%)K!:Sj#FPWCZK!>-)!&(-(6&(6?&!?/GG%?(%)!/!6(!-(!DH"a54!(>%!%V%6;!5$6/$!(/!A>%!(>6&!&?$65(U&!%@%?7(6/!(64%!6?$%-&%)L! W!>-V%!-!&?$65(!?-GG%)!&(^-GGL&XG!(>-(!6&!-!?/45/&6(%!&?$65(!(/!?-GG!&%V%$-G!)6BB%$%(!&(-(6&(6?&!?/GG%?(6/!X7%$+!&?$65(&L!W!?-!$7!(>6&!&6;G%!V%$&6/!(/!;%(!-GG!(>%!&(-(&!B/$!-!&5%?6B6%)!/*]%?(!_(-*G%!&(-(&K!?/G74!&(-(&K!6)%@!&(-(&K!%(?L`!/$!W!?-!$7!-!&?$65(!B/$!]7&(!(>%!&(-(&!W!A-(!(/!&%%L!M>-(!W!A-(%)!(/!J/A!A-&!(>%!&(-(&!B/$!(>%!?/G74&!7&%)!6!(>%!:Sj#FPWCZjia!6)%@L!I&!+/7!?-!+/7!&%%!B$/4!(>%!5$%)6?-(%!6B/$4-(6/!6!(>%!5G-K!(>%!?/G74!WU4!G//J6;!B/$!6&!3Z3jiC888D1hL!.+!&?$65(!&>/A%)!4%!(>%!B/GG/A6;!56%?%&!/B!6B/$4-(6/H! ========================================================================================================= INDEX STATISTICS ========================================================================================================= Index Name Pos# Order Column Name -------------- ---- ----- ------------- tr_policy_n5 1 ASC sys_nc00063$ 2 ASC sys_nc00064$ 3 ASC pol_sys_id 4 ASC batch_sys_id!! "8! ! ! ! ! ! ! ! ! ! !
  • 11. ! ! ! ! !! ! Index Name Column Name Pos# Expression -------------- -------------- ---- -------------------------------------------------------------- tr_policy_n5 SYS_NC00063$ 1 DECODE("POL_SUB_STAT_CD",UBE,1,VALID,2,EXCEPTION,2,0) SYS_NC00064$ 2 TRUNC("ENTERED_INTO_SYS_DTS") ========================================================================================================= COLUMN STATISTICS ========================================================================================================= Name Analyzed Null? NDV Density # Nulls # Buckets Sample AvgLen Lo-Hi Values ========================================================================================================= sys_nc00063$ 02/11/2011 18:15:53 Y 2 .000000 0 2 6953 3 0 | 2 =========================== HISTOGRAM STATISTICS =========================== SYS_NC00063$ (2 buckets) 1 97% 3/K!(>%!&(-(&!B/$!(>%!?/G74!&>/A!(>-(!(>%$%!-$%!(A/!)6&(6?(!V-G7%&!_8K!0`!-)!(>-(!/%!/B!(>%!V-G7%&!6&!5$%&%(!6!mcn!5%$?%(!/B!(>%!$/A&L!Y7(K!)6)U(!(>%!5$%)6?-(%!B/$!(>%!T#<I:E!7&%!-!V-G7%!/B!"R!Z%&f!3/K!6(!G//J&!G6J%!(>%!V-G7%!"!6&!46&&6;!B$/4!(>%!&(-(&L!W!/$)%$!(/!?/B6$4!(>6&!?>-;%!A-&!4-)%!)7%!(/!(>%!&(-(6&(6?&!?/GG%?(6/K!W!%%)%)!(/!?/45-$%!(>%!?7$$%(!&(-(&!(/!(>%!5$%V6/7&!?/GG%?(6/L!F$-?G%!-7(/4-(6?-GG+!*-?J&!75!&(-(6&(6?&!5$6/$!(/!?/GG%?(6;!-!%A!&%(!&/!W!?/7G)!57GG!(>%4!B$/4!(>%!>6&(/$+L!36?%!A%!-G&/!J%%5!*-?J75&!/B!/7$!/AK!W!/5(%)!(/!?/45-$%!(/!/7$!*-?J75!?/5+L!W!7&%)!-/(>%$!&?$65(!?-GG%)!)6BB^&(-(&^&(-((-*L&XG!(>-(!%@%?7(%&!-!)6BB%$%?%!$%5/$(!7&6;!(>%!<Y.3j3:I:3L<Wkkj:IYPEj3:I:3jWij3:I::IY!5$/?%)7$%L!2%$%!-$%!(>%!J%+!56%?%&!/B!6B/$4-(6/!W!>-)!-B(%$!%@%?7(6;!4+!&?$65(H! STATISTICS DIFFERENCE REPORT FOR: ................................. TABLE : TR_POLICY OWNER : TRAX_OWNER SOURCE A : User statistics table TRAX_STATS_BACKUP_20110211 : Statid : : Owner : TRAX_OWNER SOURCE B : Current Statistics in dictionary PCTTHRESHOLD : 1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ COLUMN STATISTICS DIFFERENCE: ............................. COLUMN_NAME SRC NDV DENSITY HIST NULLS LEN MIN MAX SAMPSIZ ............................................................................... SYS_NC00063$ A 3 .000000009 YES 0 3 80 C103 5.5E+07 B 2 .000000008 YES 0 3 80 C103 6953!! i/(6?%!(>-(!(>%!i<g!_74*%$!/B!)6&(6?(!V-G7%&`!?>-;%)!B$/4!1!(/!0!A>%!(>%!&(-(&!A%$%!?/GG%?(%)L!WB!+/7!G//J!-!*6(!?G/&%$K!+/7UGG!/(6?%!(>%!$%-&/!A>+L!:>%!&-45G%!&6[%!B/$!(>%!5$%V6/7&!?/GG%?(6/!A-&!)/%!-(!"88n!_/(%!(>%!&-45G%!&6[%!V-G7%!/B!aLaEo8c`!-&!?/45-$%)!(/!-!&-45G%!&6[%!/B!]7&(!7)%$!c888!$/A&!B/$!(>%!G-(%&(!?/GG%?(6/L!I55-$%(G+K!(>%!&4-GG%$!&-45G%!A-&U(!*$/-)!%/7;>!(/!?-5(7$%!-+!/B!(>%!$/A&!(>-(!>-)!-!V-G7%!/B!"!B/$!(>-(!?/G74L!3/K!(>%!>6&(/;$-4!/G+!>-)!(A/!*7?J%(&K!/%!B/$!8!V-G7%&!-)!/%!B/$!0!V-G7%&L!36?%!-!"U&!*7?J%(!A-&!46&&6;K!(>%!/5(646[%$!?/457(%)!&%G%?(6V6(+!B/$!(>%!7J/A!V-G7%!*-&%)!/!>-GB!(>%!466474!J/A"!?-$)6-G6(+!V-G7%&!-$$6V6;!-(!-!$/A&!%&(64-(%!/B!1c!46GG6/L!:>6&!%&(64-(%!?-7&%)!(>%!/5(646[%$!(/!?>//&%!-!&7*^/5(64-G!YW:.I#!CFigES3WFi!5G-!/5%$-(6/!(/!($+!-)!$%)7?%!(>%!%BB/$(!(/!&?-!1c!46GG6/!$/A&!*+!)/6;!-!YW:.I#!Ii<!A6(>!-/(>%$!6)%@!/!(>%!&(-(%!?/G74!_&(-(%!A-&!-G&/!7&%)!6!(>%!5$%)6?-(%`L!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" !3%%!b/-(>-!P%A6&U!*G/;!%($6%&!/!(>6&!&7*]%?(!-(!4))56778(%")4"%-$2,3&2(#15#$33&.(79::;7:<79=7>#$?@$%.AB4,3)(+#"37!-)!4))56778(%")4"%-$2,3&2(#15#$33&.(79:C:7:D79D7>"!$B4,3)(+#"37L!!! ! ! ! ""!
  • 12. ! ! !! 36?%!(>%!$%-G6(+!A-&!(>-(!(>%$%!A%$%!V-G7%&!/B!"!6!(>-(!?/G74K!(>-(!6B/$4-(6/!%%)%)!(/!*%!-V-6G-*G%!(/!(>%!/5(646[%$!6!/$)%$!B/$!6(!(/!*%!-*G%!(/!4-J%!(>%!5$/5%$!&%G%?(6V6(+!%&(64-(%&L!M>-(!)/!A%!)/R!M%GGK!A%!?/7G)!?/GG%?(!&(-(&!-GG!/V%$!-;-6!-(!"88nL!:>-(U&!5$%?6&%G+!A>-(!>-)!*%%!)/%!6!(>%!5$%V6/7&!?/GG%?(6/L!Y7(K!)/6;!&/!A/7G)!(-J%!&%V%$-G!>/7$&!-)!A/7G)!*7$!-!G/(!/B!$%&/7$?%&!-)!$%?/GG%?(!&(-(&!/!-GG!(>%!/(>%$!?/G74&!(>-(!$%-GG+!)6)U(!%%)!(/!*%!$%?/GG%?(%)L!!! S-(>%$!(>-!A-&(%!-GG!(>-(!(64%!-)!%BB/$(K!W!/5(%)!(/!4-7-GG+!&%(!(>%!&(-(6&(6?&!(/!(>%!V-G7%&!W!J%A!A%$%!%%)%)L!W!(>6&!?-&%K!W!J%A!W!%%)%)!(/!*745!75!(>%!74*%$!/B!)6&(6?(!V-G7%&!(/!1!-)!&%(!(>%!-55$/5$6-(%!V-G7%&!B/$!(>%!46&&6;!*7?J%(!6!(>%!>6&(/;$-4L!P7?J6G+K!W!>-)!-/(>%$!&?$65(!(>-(!-GG/A%)!4%!(/!4-J%!(>/&%!4/)6B6?-(6/&!X76?JG+!_&%(>&(-(&L&XGK!&>/$(!B/$!&%(!>6&(/;$-4!&(-(&`L!!! M6(>!(>%!%A!&(-(&!6!5G-?%K!W!(%&(%)!(>%!75)-(%!-;-6!-)!A-&!5G%-&%)!(>-(!%V%$+(>6;!A-&!*-?J!(/!/$4-Gf!:>%!%(6$%!5$/?%&&!(//J!4%!-*/7(!"8!467(%&!-)!4/&(!/B!(>-(!A-&!&5%(!)/?74%(6;!A>-(!W!A-&!)/6;!-&!W!A%(!-G/;!5G7&!(-J6;!(64%!(/!)/7*G%^?>%?J!4+&%GB!(>$/7;>!%-?>!&(%5L!Y7(K!(>%!*/((/4^G6%!A-&!(>-(!W!>-)!(//G&!_&?$65(&!6!(>6&!?-&%`!$%-)6G+!-(!>-)!(>-(!W!?/7G)!7&%!(/!;%(!(>%!6B/$4-(6/!W!%%)%)!(/!6)%(6B+!(>%!$//(!?-7&%!/B!(>%!5$/*G%4!-)!(>%!)%(%$46%!(>%!B6@!%%)%)!(/!?/$$%?(!6(L!! I&!6(!(7$&!/7(K!(>%!&?$65(!%)%)!75!;%((6;!-!B7$(>%$!B-?%^G6B(!(/!?>-;%!(>%!0aD!6)6V6)7-G!T#<I:E!&(-(%4%(&!(/!-!*7GJ!/5%$-(6/!-)!(/!-))!&/4%!6&($74%(-(6/!(/!>%G5!7&!;%(!(/!(>%!$//(!/B!(>%!5$/*G%4!%V%!B-&(%$!6B!(>6;&!A%(!&/7(>!-;-6!6!(>%!B7(7$%L!:>%!?>-;%!4-)%!(/!&>6B(!(/!7&6;!-!*7GJ!/5%$-(6/!6&!-?(7-GG+!/%!/B!(>%!-(65-((%$&!A%UGG!)6&?7&&!G-(%$L!7BM >+I+"N%#$&2H+&!"$%0&M$6(6;!-)!4-6(-66;!3OP!(>-(!5%$B/$4&!A%GG!/B(%!&%%4&!G6J%!-!4-;6?!($6?JL!M>%!+/7!A-(?>!&/4%/%!A/$J!(>-(!+/7!5%$?%6V%!(/!*%!-!3OP!4-;6?6-K!(>%+!-55%-$!(/!*%!-*G%!(/!4-J%!(>%!645/&&6*G%!>-55%!-)!B6)!-)!B6@!3OP!5%$B/$4-?%!6&&7%&!A6(>!G6((G%!%BB/$(L!Y7(K!6&!6(!$%-GG+!4-;6?!/$!6&!6(!]7&(!-!A%GG^$%>%-$&%)!&%(!/B!&(%5&!-)!-?(6/&!(>-(!BG/A!(/;%(>%$!%BB/$(G%&&G+!(/!5$/)7?%!-!B6-G!$%&7G(R!! Z/7!-G$%-)+!J/A!(>%!-&A%$l!6(U&!/(!4-;6?L!Y7(K!G%-$6;!>/A!(/!4-J%!6(!-55%-$!G6J%!4-;6?!(-J%&!]7&(!-&!47?>!5$-?(6?%!-&!-+!4-;6?6-!A/7G)!7&%!(/!*%?/4%!5$/B6?6%(!-(!>6&!?$-B(L!i/(!%V%$+/%!4-+!$%-?>!(>%!5$/B6?6%?+!G%V%G!/B!-!2-$$+!2/7)66!/$!<-V6)!YG-6%!_B/$!7&!F$-?G%!;%%J&K!A%!46;>(!&-+!:/4!,+(%!/$!b/-(>-!P%A6&`K!*7(!%V%$+/%!?-!G%-$!A>-(!(>%+!%%)!(/!57GG!/BB!(>%6$!($6?J&!4/&(!/B!(>%!(64%L!W(!-GG!&(-$(&!A6(>!-!B%A!*-&6?&L!7BMB9 ()&.52%/%O"2%.#&P"3%03&Z/7U$%!/(!;/6;!-+A>%$%!(/A-$)&!*%?/46;!5$/B6?6%(!-(!4--;6;!3OP!5%$B/$4-?%!7(6G!+/7!G%-$!-!*6(!/B!(>%!N7)%$!(>%!?/V%$&Q!*-&6?&L!:>%!)-(-*-&%!6&!/(!-!*G-?J!*/@K!/!4-((%$!>/A!>-$)!A%!4-+!A6&>!6(!A%$%L!W!/$)%$!(/!A$6(%!*%((%$!3OP!-)!($/7*G%^&>//(!3OP!5%$B/$4-?%!6&&7%&K!+/7!>-V%!(/!7)%$&(-)!>/A!3OP!6&!B/$47G-(%)!-)!>/A!6(!%@%?7(%&L!C/V%$6;!-GG!(>%!)%(-6G&!/B!(>%!*-&6?&!+/7!%%)!(/!?/45$%>%)!6&!*%+/)!(>%!&?/5%!/B!A>-(!A%!?-!?/V%$!6!/%!)-+K!*7(!>%$%U&!-!G6&(!/B!5$/B6?6%?6%&!+/7!%%)H! ()&34#2"Q& i/(!/G+!)/!+/7!%%)!(/!J/A!;%%$-G!&(-(%4%(!&+(-@K!*7(!(>%!B7$(>%$!+/7!?-!%@5-)!+/7$!>/$6[/&! (/!G%-$!A-+&!(/!B/$47G-(%!3OP!*%+/)!*-&6?!3EPEC:!p!kSF.!:IYPE!&(-(%4%(&K!(>%!4/$%!(//G&!+/7UGG! >-V%!A>%!B-?%)!A6(>!-!3OP!(76;!?>-GG%;%L!Z/7!%%)!(/!*%?/4%!B-46G6-$!A6(>!*76G(^6!B7?(6/&K!-)!!! "0! ! ! ! ! ! ! ! ! ! !
  • 13. ! ! ! ! !! ! 75)-(%!+/7$!J/AG%);%!A6(>!%-?>!%A!$%G%-&%L!F$-?G%!A6GG!/B(%!-))!-!B7?(6/!(>-(!+/7!4-+!>-V%! *%%!?/)6;!A/$J-$/7)&!B/$!+%-$&!_B/$!%@-45G%K!(>%!#WgF:!B7?(6/`L! ()&+Q+062%.#&P"3%03& M>%!+/7!&7*46(!-!3OP!&(-(%4%(K!A>-(!>-55%&R!Z/7!%%)!(/!J/AL!:>6&!4%-&!+/7UV%!;/(!(/! *%?/4%!B-46G6-$!A6(>!>-$)!-)!&/B(!5-$&6;K!(>%!&>-$%)!5//GK!(>%!*7BB%$!?-?>%K!G/;6?-G!-)!5>+&6?-G!WFK! -)!4/$%L!WB!+/7!)/U(!7)%$&(-)!>/A!+/7$!3OP!6&!%@%?7(%)K!>/A!?-!+/7!%@5%?(!(/!%BB%?(6V%G+!B6;7$%! /7(!>/A!(/!?>-;%!6(&!*%>-V6/$R! :H+&.52%/%O+,& :>%!?/&(^*-&%)!/5(646[%$!%%)&!(/!*%?/4%!+/7$!B$6%)L!:>%!/5(646[%$!6&!$%&5/&6*G%!B/$!)%(%$466;! >/A!+/7$!3OP!&(-(%4%(&!A6GG!%@%?7(%!&/!+/7!%%)!(/!7)%$&(-)!6(!%/7;>!(/!J/A!>/A!(/!;6V%!6(! A>-(!6(!%%)&!(/!)/!6(&!]/*!-&!%BB%?(6V%G+!-&!5/&&6*G%L!:>6&!4%-&!+/7!>-V%!(/!&5%-J!(>%!&-4%!G-;7-;%L! S%-)6;!%@%?7(6/!5G-&!>-&!(/!*%?/4%!-&!B-46G6-$!-)!%-&+!(/!+/7!-&!$%-)6;!+/7$!B-V/$6(%!4-;-[6%L! Z/7UV%!;/(!(/!7)%$&(-)!&(-(6&(6?&L!!Z/7UV%!;/(!(/!7)%$&(-)!(>%!V-$6/7&!/5%$-(6/&!(>%!/5(646[%$!?-! ?>//&%!(/!7&%!B/$!+/7$!3OPU&!%@%?7(6/L!Z/7!*-&6?-GG+!>-V%!(/!G%-$!(/!(>6J!G6J%!(>%!/5(646[%$L!! C#"N43%3&3R%NN3& Z/7!4-+!>-V%!(>%!J/AG%);%!_W!?-GG!6(!N*//J!&4-$(&Q`K!*7(!A>%!6&&7%&!-$6&%!+/7!>-V%!(/!*%!-*G%!(/! ?/GG%?(!(>%!J%+!56%?%&!/B!6B/$4-(6/!-)!57(!6(!-GG!(/;%(>%$!(/!5$/5%$G+!--G+[%!-)!)6-;/&%!(>%! 5$/*G%4L!:>6&K!6!4+!/566/K!6&!(>%!*6;;%&(!5-$(!/B!(>%!N4-;6?LQ!,/A6;!&/4%(>6;!-)!-55G+6;!A>-(! +/7!J/A!-$%!(A/!)6BB%$%(!(>6;&L!W(U&!(>%!-55G6?-(6/!/B!(>%!J/AG%);%!+/7!/*(-6!(>-(!6&!(>%!J%+L!WU4!;/6;!(/!-&&74%!+/7UV%!;/(!4/&(!/B!(>%&%!*-&%&!?/V%$%)K!/$!+/7!&//!A6GGK!-&!A%!5$/;$%&&!(>$/7;>!(>%!$%&(!/B!(>%!4-(%$6-GL!3/K!6B!W!&(-$(!(-GJ6;!-*/7(!-+(>6;!+/7U$%!7B-46G6-$!A6(>!/$!%%)!(/!$%B$%&>!+/7$!4%4/$+!-*/7(K!WUGG!($7&(!+/7!(/!)/!(>-(!-&!%%)%)L!7BMB9B9 :6#%#$&()&.+!]/*!6V/GV%&!-!G/(!/B!3OP!(76;!_W!4%-!-!G/(f`L!WUV%!*%%!)/6;!6(!B/$!&/!G/;!(>-(!A>-(!(/!)/!A>%!WU4!5$%&%(%)!A6(>!-!&(-(%4%(!(>-(!%%)&!(76;!>%G5!6&!4/&(G+!&%?/)!-(7$%L!Y7(K!6B!W!&(/5!-)!(>6J!-*/7(!(>%!&(%5&!6V/GV%)!6!(76;!-!3OP!&(-(%4%(K!6(U&!(+56?-GG+!5$%((+!&($-6;>(B/$A-$)L!!! • S%V6%A!(>%!5$/*G%4!3OP!&(-(%4%(L! • k6)!/7(!A>-(!6(U&!&755/&%)!(/!)/L!_:7%!(>%!X7%&(6/K!/(!(>%!X7%$+L`! • E@%?7(%!(>%!&(-(%4%(!-)!?-5(7$%!%@%?7(6/!5G-!)-(-!_6B!6(U&!5$/)7?(6/K!;%(! IMS=I32=3(-(&#-?J=WPF!)-(-K!%@%?7(%!6!5$/)!6B!5/&&6*G%!/$!6!5$/)7?(6/^G6J%!%V6$/4%(`L! • S%V6%A!(>%!&(-(6&(6?&!B/$!(>%!/*]%?(&!7&%)!6!(>%!&(-(%4%(L!C>%?J!6)%@%&!-)!?/&($-6(&L! • EV-G7-(%!(>%!%@%?7(6/!5G-K!?/45-$%!%&(64-(%&!V&!-?(7-G!_?-$)6-G6(+!B%%)*-?J`L! • P//J!B/$!(>%!*6;!>6((%$&!_5G-?%&!6!(>%!5G-!A>%$%!(>%!4/&(!(64%!6&!&5%(`L!! • S%B-?(/$!(>%!&(-(%4%(L! • :%&(!$%A$6((%!3OP!-)!?/45-$%!(/!/$6;6-GL! • S%B-?(/$!-)!$%5%-(!7(6G!A6(>6!3PI!/$!/!B7$(>%$!(76;!6&!5/&&6*G%L! !! ! ! ! "1!
  • 14. ! ! ! W(U&!-G&/!-!;//)!6)%-!(/!J%%5!-!%+%!/7(!B/$!?%$(-6!(>6;&!(>-(!?-!>%G5!4-J%!+/7$!(76;!(-&J&!%-&6%$L!2%$%U&!-!&>/$(!G6&(!/B!?/44/!(>6;&!W!G//J!B/$!/$!)/!A>%!WU4!(76;!3OPH! • C/&($-6(&!-$%!-!47&(f!#$64-$+!J%+&K!B/$%6;!J%+&K!?>%?J!?/&($-6(&!-$%!-GG!%@($%4%G+!645/$(-(!(/! (>%!/5(646[%$U&!-*6G6(+!(/!5$/)7?%!-!X7-G6(+!5G-L!M6(>/7(!(>%4K!(>%!/5(646[%$!]7&(!?-U(!)/!6(&!]/*!-&! %BB6?6%(G+!-&!6(!?-!A6(>!(>%4L! • Z/7UV%!;/(!(/!J/A!(>%!)-(-!-)!(>%!&?>%4-L!WB!+/7!)/U(!J/AK!-&J!X7%&(6/&!/B!&/4%/%!A>/! )/%&L! • P//J!B/$!(-*G%&!(>-(!-$%!7&%)!6!]/6&!*7(!5$/V6)%!/!?/G74&!6!(>%!/7(57(L!:>%&%!?-!/B(%!*%! %G646-(%)L! • P//J!B/$!$%5%-(%)!7&%!/B!(>%!&-4%!(-*G%&!7&6;!(>%!&-4%K!/$!&646G-$K!5$%)6?-(%&L!:>%&%!?-!/B(%!*%! $%)7?%)!(/!7&%!/?%L! • C>%?J!-V-6G-*G%!6)%@%&!-)!%V-G7-(%!(>%6$!V6-*6G6(+!-;-6&(!5$%)6?-(%&L! • P//J!B/$!7&%!/B!<W3:WiC:!/$!TiWFi!(/!$%4/V%!)75G6?-(%&L!!! W!(>%!%)K!+/7$!;/-G!6!4--;6;!3OP!5%$B/$4-?%!6&!$%-GG+!(A/^B/G)H!A$6(%!B-&(!3OP!B-&(%$!-)!B6)!-)!B6@!*-)!3OP!B-&(L!:>%$%!6&U(!$%-GG+!-+!4-;6?L!:>%!4-;6?!6&!6!>/A!A6GG6;!+/7!-$%!(/!G%-$!-)!5$-?(6?%L!M <=:>@!F=:C:<?=& qWB!+/7!?-U(!4%-&7$%!6(K!+/7!?-U(!4--;%!6(Lq!9!<-V6)!d-$V6! !W!G/V%!(>6&!X7/(%!*%?-7&%!6(!&5%-J&!(/!(>%!>%-$(!/B!4--;6;!5%$B/$4-?%L!W&($74%(-(6/!6&!-!G6((G%!%@($-!?/)%!(>-(!)%V%G/5%$&!57(!6(/!(>%6$!-55G6?-(6/&!(>-(!(%GG&!%V%$+/%!r!6?G7)6;!(>%!&/B(A-$%!)%V%G/5%$&!(>%4&%GV%&!r!%@-?(G+!A>%$%!+/7$!&/B(A-$%!6&!&5%)6;!+/7$!(64%L!M6(>!6(K!4--;6;!5%$B/$4-?%!6&!-!&-5L! d//)!6&($74%(-(6/!4-J%&!6(!&/!/$4-G!5%/5G%K!/(!]7&(!&5%?6-G6&(&K!?-!)6-;/&%!-)!&/GV%!5%$B/$4-?%!5$/*G%4&!X76?JG+!-)!5%$4-%(G+K!/B(%!*%B/$%!+/7$!7&%$&!%V%!&%&%!&/4%(>6;!6&!A$/;L!2/A%V%$K!A6(>/7(!;//)!(64%^*-&%)!5%$B/$4-?%!6&($74%(-(6/K!4--;6;!5%$B/$4-?%!*%?/4%&!6;>(4-$6&>G+!?/45G%@!-)!%@5%&6V%L! M6(>!-&!G6((G%!-&!(A/!G6%&!/B!?/)%!+/7!A6GG!*%!-*G%!(/!4/6(/$!&5%?6B6?!(-&J&!6!+/7$!-55G6?-(6/!-)!4-J%!/%!/B!(>%!4/&(!)6BB6?7G(!&(%5&!/B!645G%4%(6;!$%&5/&%^(64%!*-&%)!5$/*G%4!)6-;/&6&!_.%(>/)!S`!6(/!/%!/B!(>%!%-&6%&(L!W!-))6(6/K!(>%&%!(%?>6X7%&!A6GG!%-*G%!+/7!(/!?/$$%G-(%!)-(-*-&%!&(-(6&(6?&!*-?J!(/!*7&6%&&!(-&J&!-)!>%G5!)6&?/V%$!(>/&%!(-&J&!(>-(!-$%!>%-V+!$%&/7$?%!?/&74%$&L!MB9 SH4&%3&/4&5,.$,"/&3N.KT&M>%!6&!&/4%(>6;!&G/AR!M%!-$%!(+56?-GG+!4-)%!-A-$%!/B!&G/A%&&!*+!-!7&%$!?/45G-6(L!3G/A!6&!$%G-(6V%!>/A%V%$L!WB!+/7!&-+!6(!(-J%&!"!>/7$!(/!;%(!B$/4!5/6(!I!(/!5/6(!YK!?/7G)!+/7!-&A%$!(>%!N6&!(>6&!&G/AQ!X7%&(6/!A6(>!/G+!(>-(!*6(!/B!6B/$4-(6/R!i/L!Z/7!%%)!(/!-(!G%-&(!J/A!A>-(!(>%!)6&(-?%!6&!B$/4!5/6(!I!(/!5/6(!Y!-)!>-V%!-!6)%-!/B!(>%!$%-&/-*G%!%@5%?(-(6/!B/$!>/A!G/;!6(!&>/7G)!(-J%!(/!;%(!B$/4!/%!5/6(!(/!(>%!/(>%$L!WB!(>%!)6&(-?%!6&!>7)$%)&!/$!(>/7&-)&!/B!46G%&K!"!>/7$!46;>(!*%!V%$+!$%-&/-*G%K!*7(!6B!(>%!)6&(-?%!6&!08!B%%(K!"!>/7$!4-+!*%!%@($-/$)6-$6G+!G/;L!!! "! ! ! ! ! ! ! ! ! ! !
  • 15. ! ! ! ! !! ! :/!)%(%$46%!A>+!-!5$/;$-4!6&!&G/AK!G%(U&!&(-$(!*+!A-GJ6;!(>$/7;>!(>%!--G+&6&!/B!-!5$/?%)7$%!-4%)!#L!#!6&!$76;!3-(2L!3/K!B6$&(!W!%%)!(/!J/A!%@-?(G+!A>-(!&G/A!4%-&!6!(%$4&!/B!$%&5/&%!(64%L! SQL> set timing on SQL> exec p PL/SQL procedure successfully completed. Elapsed 00:02:09:98 F?%!W!>-V%!-!*-&%!(646;!/B!0!467(%&!mLme!&%?/)&K!W!?-!/5%!75!(>%!?/)%!-)!($+!-)!)%(%$46%!A>%$%!(/!;/!B$/4!(>%$%L!:>%!?/)%!B/$!#!6&H! create or replace procedure p as begin q; r; s; end; /i/A!A>-(R!#!?-GG&!(>$%%!/(>%$!5$/?%)7$%&L!3/K!>/A!)/!W!J/A!A>%$%!(/!&(-$(R!M%GGK!W!?/7G)!&645G+!/5%!75!(>%!B6$&(!5$/?%)7$%K!OK!-)!&%%!6B!W!?-!B6)!-+!645$/V%4%(&!(/!*%!4-)%!(>%$%L!Y7(K!4-+*%!6(!A/7G)!*%!>%G5B7G!(/!*%!-!G6((G%!4/$%!6B/$4%)!*%B/$%!W!&(-$(!($+6;!(/!G//J!B/$!-$%-&!(/!645$/V%L!2%$%U&!A>%$%!6&($74%(-(6/!?/4%&!6L!WUGG!-))!-!G6((G%!?/)%!(/!>%G5!4%!4%-&7$%!A>%$%!(>%!%@%?7(6/!/B!#!&5%)&!6(U&!(64%H! create or replace procedure p as t0 number; t1 number; t2 number; t3 number; begin t0 := dbms_utility.get_time; q; t1 := dbms_utility.get_time ; dbms_output.put_line (Procedure q: || to_char((t1 - t0)/100)); r; t2 := dbms_utility.get_time ; dbms_output.put_line (Procedure r: || to_char((t2 - t1)/100)); s; t3 := dbms_utility.get_time ; dbms_output.put_line (Procedure s: || to_char((t3 - t2)/100)); dbms_output.put_line (Total R : || to_char((t3 - t0)/100)); end; /!i/A!(>-(!WUV%!-))%)!&/4%!?/)%!(/!>%G5!?-5(7$%!(646;!)%(-6G!-(!-!4/$%!;$-7G-$!G%V%GK!G%(U&!%@%?7(%!#!-;-6L! SQL> set timing on SQL> exec p Procedure q: 1 Procedure r: 114 Procedure s: 15 Total R : 130 Elapsed 00:02:09:99! M6(>!(>6&!6B/$4-(6/K!/A!W!J/A!A>%$%!(>%!(64%!6&!&5%(L!:>%!4-]/$6(+!/B!(64%!6&!&5%(!%@%?7(6;!5$/?%)7$%!SL!:>-(U&!;$%-(!6B/$4-(6/!(/!>-V%L!Y7(K!A>-(!)6)!6(!?/&(!B/$!4%!(/!>-V%!(>6&!6B/$4-(6/R!i/(!47?>!$%-GG+L!:>%!(/(-G!%@%?7(6/!(64%!6?$%-&%)!*+!L8"!&%?/)&!_B$/4!"0mLme!(/!"0mLmm`L!W!>-)!(/!4-J%!&/4%!-))6(6/&!(/!(>%!?/)%H!!%A!V-$6-*G%&!-)!e!G6%&!/B!?/)%!(/!?-5(7$%!(646;!)-(-L!:>%!&4-GG!%BB/$(!%((%)!*6;!$%&7G(&!6!(>-(!/A!W!J/A!A>%$%!(/!B/?7&!4+!-((%(6/L!! ! ! ! "a!
  • 16. ! ! !! M>%$%!A/7G)!+/7!>-V%!&(-$(%)!6B!+/7!)6)U(!>-V%!(>6&!)-(-R!./$%!645/$(-(G+K!A>-(!A/7G)!>-55%!6B!+/7!&(-$(%)!(/!A/$J!/!5$/?%)7$%!O!/$!3!B6$&(R!Y-&%)!/!(>%!(646;!)-(-!?/GG%?(%)K!%V%!6B!A%!?/7G)!$%)7?%!(>%!%@%?7(6/!(64%&!/B!*/(>!/B!(>/&%!5$/?%)7$%&!(/!8K!A%!4-+!&(6GG!*%!B-?%)!A6(>!-!5$/;$-4!(>-(!6&!N(//!&G/ALQ!!MB7 SH"2&%3&%#32,6/+#2"2%.#&"#D&KH4&%3&%2&%/5.,2"#2T&W&($74%(-(6/!6&!(>%!A-+!+/7!4-J%!(>%!5%$B/$4-?%!/B!+/7$!-55G6?-(6/&!%-&+!(/!4/6(/$!-)!$%V6%AL!W!;%%$-GK!(>%!57$5/&%!/B!6&($74%(-(6/!6&!(/H! • .%-&7$%!(>%!-(($6*7(%&!/B!-!&+&(%4! • C$%-(%!-!4/6(/$6;!4%?>-6&4! • :$-?J!-55G6?-(6/!5%$B/$4-?%!#$/5%$!6&($74%(-(6/!-GG/A&!+/7!(/!?/GG%?(!5$/5%$G+!&?/5%)!(646;!-)!($-?%!6B/$4-(6/!B/$!(>%!(-&J&!(>-(!-$%!645/$(-(!(/!+/7$!*7&6%&&L!W&($74%(-(6/!&>/7G)!*%!G6;>(A%6;>(!-)!%-&+!(/!-?(6V-(%!-)!7G(64-(%G+!4-J%!(>%!*7&6%&&!/B!B6)6;!-)!B6@6;!5%$B/$4-?%!6&&7%&!X76?J!-)!&645G%L!! M6(>!6&($74%(-(6/K!+/7!?-!%-&6G+!-&A%$!X7%&(6/&!G6J%H! • M>+!)6)!(>6&!(-J%!&/!G/;R! • M>-(!A/7G)!>-55%!6BR! • W&!(>6&!(>6;!%BB6?6%(R! • I4!W!)/%!+%(R!Y%6;!-*G%!(/!-&A%$!(>%&%!X7%&(6/&!A6GG!-GG/A!+/7!(/!5$/V6)%!(>%!B6-G!A/$)!/!)6&57(%&!*%(A%%!<YI&K!)%V%G/5%$&K!4--;%$&K!-)!7&%$&L!Z/7!J/A!A>%$%!+/7$!-55G6?-(6/!&5%)&!6(&!(64%!-)!+/7!?-!B/?7&!/!B6@6;!(>%!&5%?6B6?!-$%-&!A>%$%!(//!47?>!(64%!6&!G/&(L!MBM 1.K&D.&4.6&"DD&%#32,6/+#2"2%.#T&F$-?G%!&755G6%&!*76G(^6!5-?J-;%&!(>-(!?-!*%!7&%)!-&!(>%!*76G)6;!*G/?J&!B/$!6&($74%(6;!+/7$!?/)%L!:>%$%!-$%!(>$%%!5$64-$+!5-?J-;%&!(>-(!?-!>-)G%!-G4/&(!%V%$+!%G%4%(!%%)%)!(/!)/!(>%!]/*!5$/5%$G+H! • <Y.3j3E33WFi! • <Y.3j3Z3:E.! • <Y.3jI##PWCI:WFijWikF!MBMB9 ;U!VF<?=&:>6&!5-?J-;%!6&!7&%)!(/!A$-5!-??%&&!(/!IP:ES!3E33WFi!-)!3E:!SFPE!&(-(%4%(&!-&!A%GG!-&!/(>%$!&%&&6/!6B/$4-(6/L!M>6G%!(>%$%!-$%!74%$/7&!&7*5$/;$-4&!-V-6G-*G%K!(>%!3E:jW<Ei:WkWES!5$/?%)7$%!6&!/B!5$64-$+!7&%!A>%!?$%-(6;!6&($74%(-(6/!B/$!+/7$!?/)%L!! T&6;!3E:jW<Ei:WkESK!+/7!-$%!-*G%!(/!%&(-*G6&>!(>%!?7$$%(!&%&&6/!A6(>!-!?G6%(!6)%(6B6%$L!:>-(!6)%(6B6%$!A6GG!(>%!*%!-&&/?6-(%)!A6(>!(>-(!&%&&6/!7(6G!6(!)6&?/%?(&!/$!?G%-$&!(>%!6)%(6B6%$L!:>%!?G6%(!6)%(6B6%$!+/7!?>/&%!?-!*%!75!(/!D!?>-$-?(%$&!6!G%;(>L!FV%$!8!)+-46?!V6%A&K!&7?>!-&!gh3E33WFiK!?/(-6!-!?G6%(j6)%(6B6%$!/$!?G6%(j6)!?/G74L!F?%!+/7!&%(!(>6&!V-G7%K!6(!A6GG!*%!7&%)!(/!5/57G-(%!(>%&%!V6%A!?/G74&!(>7&!-GG/A6;!+/7!(/!X7%$+!(>%4!(/!G/?-(%!&%&&6/!6B/$4-(6/!&5%?6B6?!(/!(>-(!6)%(6B6%$L!!! "D! ! ! ! ! ! ! ! ! ! !
  • 17. ! ! ! ! !! !! :>%!?-GG!(/!3E:jW<Ei:WkWES!?-!*%!4-)%!-(!-+!5/6(!6!(64%K!*7(!-!5$-?(6?-G!/5(6/!46;>(!*%!(/!>-V%!(>%!6)%(6B6%$!&%(!V6-!-!G/;/!($6;;%$L!Z/7!?-!-??%&&!6B/$4-(6/!-*/7(!(>%!&%&&6/!-G$%-)+!-V-6G-*G%!B$/4!3Z3jCFi:Es:!-)!5/57G-(%!(>%!?G6%(j6)%(6B6%$!644%)6-(%G+!75/!G/;/L!:>-(!A-+K!(>%!&%&&6/!6&!6)%(6B6%)!644%)6-(%G+L!k/$!%@-45G%K!+/7!?/7G)!?$%-(%!-!G/;/!($6;;%$!&/4%(>6;!G6J%!(>6&H! CREATE OR REPLACE TRIGGER client_id_logon_trg AFTER LOGON ON DATABASE DECLARE my_service SYS.V_$SESSION.SERVICE_NAME%TYPE; my_clientid SYS.V_$SESSION.CLIENT_IDENTIFIER%TYPE; my_ip_address SYS.V_$SESSION.TERMINAL%TYPE; my_os_user SYS.V_$SESSION.OSUSER%TYPE; my_audsid SYS.V_$SESSION.AUDSID%TYPE; my_program SYS.V_$SESSION.PROGRAM%TYPE; CLIENT_ID_DELIM CHAR(1) := ~; BEGIN IF USER NOT IN (SYS) AND USER IS NOT NULL THEN my_clientid := SYS_CONTEXT(USERENV, CLIENT_IDENTIFIER); IF my_clientid IS NULL THEN my_service := SYS_CONTEXT(USERENV, SERVICE_NAME); my_ip_address := NVL(SYS_CONTEXT(USERENV, IP_ADDRESS),SYS_CONTEXT(USERENV, TERMINAL)); my_os_user := SYS_CONTEXT(USERENV, OS_USER); my_audsid := TO_NUMBER(SYS_CONTEXT(USERENV, SESSIONID)); SELECT PROGRAM INTO my_program FROM SYS.V_$SESSION WHERE AUDSID = my_audsid AND ROWNUM = 1; DBMS_SESSION.SET_IDENTIFIER(my_os_user || CLIENT_ID_DELIM || my_ip_address || CLIENT_ID_DELIM || my_program || CLIENT_ID_DELIM || my_service); END IF; END IF; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(client_id_logon_trg: Exception thrown); END client_id_logon_trg;MBMB7 ;U!VW:F!&:>6&!5-?J-;%!?/(-6&!-!74*%$!/B!5$/?%)7$%&!(>-(!?-!*%!7&%B7G!5-$(6?7G-$G+!B/$!%46((6;!4%-6;B7G!6B/$4-(6/!(/!($-?%!B6G%&!-)!-G%$(!G/;&L!F$-?G%!)/%&U(!B/$4-GG+!)/?74%(!(>6&!5-?J-;%!/$!%@5G6?6(G+!&755/$(!6(!&/!5$/?%%)!-(!+/7$!/A!$6&J!A>%!7&6;!6(L!! :>%!(A/!4-6!5$/?%)7$%&!(/!>%G5!6&($74%(!+/7$!?/)%!-$%!,3<<<:!-)!,3<MS:L!,3<<<:!?-!*%!?-GG%)!(/!%46(!-!)-(%=(64%!&(-45!6(/!-!($-?%!B6G%L!:>6&!?-!*%!>%G5B7G!B/$!%@5G6?6(G+!6)%(6B+6;!(>%!(64%!-(!A>6?>!?%$(-6!-?(6/&!+/7!-$%!4/6(/$6;!*%;6!-)!%)L!:>%!,3<MS:!5$/?%)7$%!-G&/!A$6(%&!(/!-!($-?%!B6G%K!/$!(/!(>%!-G%$(!G/;!-&!A%GGK!*7(!/BB%$&!(>%!-*6G6(+!(/!A$6(%!/7(!-+!4%&&-;%!+/7!?>//&%L!I;-6K!(>6&!?-!>%G5!+/7!5G-?%!6B/$4-(6/!6(/!($-?%!B6G%&!(>-(!4-J%&!(>%4!%-&6%$!(/!&?/5%!(/!&5%?6B6?!(-&J&!-&!(>%+!/??7$L!MBMBM ;U!VC**)<AC:<?=V<=G?&:>%!<Y.3jI##PWCI:WFijWikF!5-?J-;%!6&!(>%!%&&%(6-G!%G%4%(!7&%)!(/!-&&6&(!?/)%!6&($74%(-(6/L!:>6&!5-?J-;%!-GG/A&!+/7!(/!6)%(6B+!&5%?6B6?!&%?(6/&!/B!+/7$!?/)%!*+!4-$J6;!(>%4!A6(>!76X7%G+!6)%(6B+6;!4/)7G%!-)!-?(6/!-4%&L!:>%&%!4/)7G%!-)!-?(6/!V-G7%&!A6GG!*%!$%?/$)%)!-)!4-)%!V6&6*G%!(>$/7;>!74%$/7&!gh!V6%A&!(/!>%G5!+/7!6)%(6B+!-?(6V6(6%&!-&&6;%)!(/!-)!$%&/7$?%&!7&%)!*+!(>%!?/)%!%@%?7(%)!A6(>6!(>%&%!4/)7G%=-?(6/!5-6$!6)%(6B6?-(6/&L!i/(!/G+!-$%!(>%!4/)7G%=-?(6/!5-6$&!7&%)!(/!($-?J!-?(6V6(6%&!*7(!(>%+!?-!*%!7&%)!(/!>%G5!(7$!($-?6;!/!-)!/BB!-&!A%GGL!! :>%!3E:j.F<TPE!-)!3E:jIC:WFi!5$/?%)7$%&!-$%!7&%)!(/!&%(!(>%!-4%!/B!(>%!?7$$%(!-55G6?-(6/!/$!4/)7G%L!:>%!4-6!)6BB%$%?%!*%(A%%!(>%!(A/!6&!(>-(!3E:j.F<TPE!-GG/A&!+/7!(/!&%(!*/(>!-!4/)7G%j-4%!! ! ! ! "c!
  • 18. ! ! !-)!-?(6/j-4%!6!-!&6;G%!?-GGK!A>%$%-&!3E:jIC:WFi!/G+!&%(&!(>%!-?(6/j-4%L!T&6;!3E:j.F<TPEK!+/7!?-!%&(-*G6&>!(>%!&(-$(!/B!-!*7&6%&&!(-&J!-)!-!5-$(6?7G-$!-?(6/!A6(>6!(>-(!(-&J!-&!B/GG/A&H! DBMS_APPLICATION_INFO. set_module( module_name=>Order Entry, action_name=>Get Order Items):>%!4/)7G%!6&!6)%(6B6%)!-&!tF$)%$!E($+U!-)!(>%!-?(6/!6&!td%(!F$)%$!W(%4&UL!:>%!tF$)%$!E($+U!4/)7G%!?/7G)!?/(-6!47G(65G%!-?(6/&!6!-))6(6/!(/!(>%!td%(!F$)%$!W(%4&U!&7?>!-&!t<%G%(%!F$)%$!W(%4&U!/$!tT5)-(%!F$)%$!W(%4&UL!! :>%!?-GG&!(/!3E:j.F<TPE!/$!3E:jIC:WFi!&>/7G)!*%!5G-?%)!-(!(>%!&(-$(!/B!(>%!5-$(6?7G-$!*7&6%&&!(-&J!-)!*%!$%&%(!_6L%L!&%(!(/!7GG`!A>%!(>-(!(-&J!6&!?/45G%(%!/$!A>%%V%$!-!%$$/$!/??7$&L!W!/$)%$!(/!>%G5!6)%(6B+!(>%!?7$$%(!4/)7G%!-)!-?(6/!(>-(!6&!6!5G-?%K!(>%!SEI<j.F<TPE!5$/?%)7$%!6&!7&%)L!M>%%V%$!+/7!$%&%(!(>%!4/)7G%!-)!-?(6/!-(!(>%!*%;66;!/B!-!(-&JK!+/7!&>/7G)!4-J%!&7$%!(/!?>%?J!6B!-!4/)7G%=-?(6/!6&!-G$%-)+!6!5G-?%L!WB!&/K!+/7!A/7G)!&(/$%!(>-(!6B/$4-(6/!-)!(>%!$%&%(!4/)7G%!-)!-?(6/!(/!(>/&%!V-G7%&!A>%!(>%!?7$$%(!(-&J!?/45G%(%&L!:>%!B/GG/A6;!G6&(6;!5$/V6)%&!-!&>/$(!%@-45G%H! PROCEDURE get_emp_simple_instr IS fnlist_stack fnlist_tab; lnlist_stack lnlist_tab; BEGIN DBMS_APPLICATION_INFO.set_module(module_name => Human Resources ,action_name => Get Employees); SELECT first_name, last_name BULK COLLECT INTO fnlist_stack, lnlist_stack FROM employees; DBMS_APPLICATION_INFO.set_module(NULL, NULL); EXCEPTION WHEN OTHERS THEN DBMS_APPLICATION_INFO.set_module(NULL, NULL); DBMS_OUTPUT.PUT_LINE(HR_Package.get_emp_simple_instr => ERROR); END get_emp_simple_instr; :>6&!%@-45G%!A/$J&!]7&(!B6%!-)!A6GG!&%(!(>%!4/)7G%!-)!-?(6/!-(!(>%!*%;66;!/B!(>%!?/)%!*/)+!-)!$%&%(!6(!-(!(>%!%)K!6B!&7??%&&B7GK!/$!A6(>6!(>%!%@?%5(6/!>-)G%$!6B!-!%$$/$!/??7$&L!Y7(K!A>-(!A/7G)!>-55%!6B!(>6&!5$/?%)7$%!A-&!?-GG%)!6&6)%!-/(>%$!5$/?%)7$%!(>-(!A-&!&646G-$G+!6&($74%(%)!-&!B/GG/A&R! PROCEDURE get_emp_jobs_instr_flawed IS jtlist_stack jtlist_tab; lnlist_stack lnlist_tab; BEGIN DBMS_APPLICATION_INFO.set_module(module_name => Human Resources, action_name => Get Employees and Jobs); get_emp_simple_instr; SELECT last_name, job_title BULK COLLECT INTO lnlist_stack, jtlist_stack FROM employees e, jobs j WHERE e.job_id = j.job_id; DBMS_APPLICATION_INFO.set_module(NULL, NULL); EXCEPTION WHEN OTHERS THEN DBMS_APPLICATION_INFO.set_module(NULL, NULL); DBMS_OUTPUT.PUT_LINE(get_emp_jobs_instr_flawed => ERROR); END get_emp_jobs_instr_flawed; i/(%!(>-(!-B(%$!(>%!4/)7G%!-)!-?(6/!-$%!&%(!6!(>6&!5$/?%)7$%K!/7$!/(>%$!5$/?%)7$%!6&!?-GG%)L!M>-(U&!(>%!5$/*G%4R!:>%!5$/*G%4!6&!(>-(!644%)6-(%G+!-B(%$!(>%!4/)7G%!-)!-?(6/!-$%!&%(!B/$!(>6&!5$/?%)7$%K!(>%!;%(j%45j&645G%j6&($!5$/?%)7$%!6&!?-GG%)!-)!6&6)%!(>-(!5$/?%)7$%K!(>%!4/)7G%!-)!-?(6/!-$%!&%(!(/!V-G7%&!&5%?6B6?!(/!(>-(!5$/?%)7$%L!I(!(>%!%)!/B!(>-(!?-GGK!(>%!4/)7G%!-)!-?(6/!-$%!&%(!(/!7GGL!:>%$%B/$%K!A>%!(>%!3EPEC:!&(-(%4%(!6&!%@%?7(%)!-B(%$!(>-(!5$/?%)7$%!?-GG!?/45G%(%&K!/7$!?7$$%(!4/)7G%!-)!-?(6/!>-V%!*%%!G/&(L!:>6&!6&!A>%$%!A%!%%)!(/!4-J%!&7$%!?-5(7$%!(>%!4/)7G%!-)!-?(6/!V-G7%&!-)!$%(-6!(>%4!&/!(>-(!A%!?-!!! "e! ! ! ! ! ! ! ! ! ! !
  • 19. ! ! ! ! !! !-GA-+&!$%&%(!(>%4!5$/5%$G+!A>%!?-GG&!-$%!4-)%!(/!/(>%$!6&($74%(%)!5$/?%)7$%&L!:>%!5$/5%$!A-+!(/!?/)%!(>%!/$6;6-G!5$/?%)7$%!A/7G)!*%!G6J%!(>6&H! PROCEDURE get_emp_instr_good IS fnlist_stack fnlist_tab; lnlist_stack lnlist_tab; preModuleName VARCHAR2(48) := NULL; preActionName VARCHAR2(32) := NULL; BEGIN DBMS_APPLICATION_INFO.read_module( module_name => preModuleName, action_name => preActionName); DBMS_APPLICATION_INFO.set_module( module_name => Human Resources, action_name => Get Employees); SELECT first_name, last_name BULK COLLECT INTO fnlist_stack, lnlist_stack FROM employees; DBMS_APPLICATION_INFO.set_module( module_name => preModuleName, action_name => preActionName); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(HR_Package.get_emp_instr_good ERROR); DBMS_APPLICATION_INFO.set_module( module_name => preModuleName, action_name => preActionName); END get_emp_instr_good; i/A!(>%!?-GG6;!5$/?%)7$%U&!4/)7G%!-)!-?(6/!A6GG!*%!5$%&%$V%)!5$/5%$G+L!!MBX !"R%#$&%#32,6/+#2"2%.#&+"34&T&6;!(>%!&755G6%)!5-?J-;%&!6&!$%G-(6V%G+!&($-6;>(^B/$A-$)!*7(!)/%&!$%X76$%!&/4%!4--;%4%(!/B!(>%!?-GG!&(-?J!&/!(>-(!+/7!4-6(-6!(>%!5$/5%$!4/)7G%=-?(6/!&%((6;&!-&!+/7!?>-;%!(-&J&L!k/$(7-(%G+K!(>%$%!6&!-!B$%%K!F5%!3/7$?%!5-?J-;%!?-GG%)!(>%!W&($74%(-(6/!P6*$-$+!B/$!F$-?G%!_WPF`!-V-6G-*G%!-(!3/7$?%k/$;%!_4))56773(@#.$>(#+$&%$)75#(8$.)37,-(`!(>-(!>-&!*%%!A$6((%!-)!4-6(-6%)!*+!.%(>/)!S!C/$5/$-(6/!(>-(!%?-5&7G-(%&!(>%!7&%!/B!(>%!5-?J-;%&!A%UV%!]7&(!)6&?7&&%)!-)!4-J%&!6(!)%-)!&645G%!(/!645G%4%(L! :>%!B/GG/A6;!&%?(6/!6&!?/56%)!B$/4!(>%!.%(>/)!S!A%*&6(%!-(!4))5677$)4(1B#&.(73(>)2"#$7,-(L!WPFK!(>%!6&($74%(-(6/!G6*$-$+!B/$!F$-?G%K!6&!-!/5%!&/7$?%!5$/]%?(!)6$%?(%)!*+!.%(>/)!S!C/$5/$-(6/!)%V%G/5%$&L!W(!?/(-6&!#P=3OP!5$/?%)7$%&!B/$!4%-&7$6;!(-&J&!7&6;!F$-?G%!%@(%)%)!3OP!($-?%L!:>%!5$/?%)7$%&!-$%!6&(-GG%)!-)!?/456G%)!6!(>%!(-$;%(!F$-?G%!6&(-?%!-)!?-!*%!?-GG%)!*+!?/)%!A$6((%!6!-+!G-;7-;%!(>-(!>-&!-??%&&!(/!(>%!F$-?G%!)-(-*-&%!(6%$L!WPF!6&!B7GG+!6(%;$-(%)!A6(>!(>%!.%(>/)!S!3PI!.--;%$K!A>6?>!-GG/A&!+/7!(/!/$;-6[%!-)!--G+[%!$%&5/&%!(64%!)-(-!B/$!+/7$!%(6$%!-55G6?-(6/!&+&(%4L!!MBXB9 <#32,6/+#2"2%.#&)%P,",4&-.,&?,"0N+&Y<)?Z&<6-;/&6;!-)!$%5-6$6;!5%$B/$4-?%!5$/*G%4&!6!-!F$-?G%!%V6$/4%(!?-!*%!-!?/45G6?-(%)!-)!(64%^?/&746;!]/*L!2/A%V%$K!+/7K!(>%!I55G6?-(6/!<%V%G/5%$K!?-!4-J%!(>%!]/*!47?>!&645G%$!*+!6&%$(6;!-!B%A!%@($-!G6%&!/B!?/)%K!?-GG%)!6&($74%(-(6/K!6(/!+/7$!-55G6?-(6/&L!M6(>!(>%!$6;>(!6&($74%(-(6/!G6*$-$+K!(>%!]/*!6&!%-&+L!:>%!W&($74%(-(6/!P6*$-$+!B/$!F$-?G%!_WPF`!;6V%&!+/7!(>%!G6%&!/B!?/)%!+/7!%%)L!MBXB7 :H+&*"4.--&W&($74%(-(6/!4-J%&!+/7$!?/)%!B-&(%$K!%-&6%$!(/!4-6(-6K!-)!?>%-5%$!(/!A$6(%L!W&($74%(-(6/!4-J%&!+/7$!?/)%!B-&(%$!*%?-7&%!6(!&>/A&!+/7!-GG!/B!+/7$!/55/$(76(6%&!B/$!4-J6;!+/7$!?/)%!4/$%!%BB6?6%(K!$6;>(!A>6G%!+/7u$%!A$6(6;!6(L!W&($74%(-(6/!4-J%&!+/7$!?/)%!%-&6%$!(/!4-6(-6!*%?-7&%!6(!&>/A&!+/7!%@-?(G+!A>-(!+/7$!--G+&(&!-$%!(-GJ6;!-*/7(!A>%!(>%+!&-+!(>-(!+/7$!?/)%!6&!(//!&G/AL!W&($74%(-(6/!4-J%&!+/7$!?/)%!?>%-5%$!(/!A$6(%!*%?-7&%!6(!B/?7&%&!+/7$!(76;!%BB/$(&!/G+!75/!(>%!5-$(&!/B!+/7$!?/)%!A>%$%!5%$B/$4-?%!$%-GG+!4-((%$&L!d//)!6&($74%(-(6/!6&!+/7$!64476[-(6/!-;-6&(!(>%!&6&!/B!5$%4-(7$%!/5(646[-(6/L!! ! ! ! "m!
  • 20. ! ! !MBXBM 1.K&<2&S.,R3&WPF!6&!&75%$!%-&+!B/$!&/B(A-$%!)%V%G/5%$&!(/!7&%L!Z/7!4-$J!(>%!*%;66;!-)!%)!/B!+/7$!(-&J&!A6(>!-!&6;G%!G6%!/B!?/)%K!;6V6;!%-?>!(-&J!-!4/)7G%!-)!-?(6/L!:>6J!/B!(>%!-?(6/!-&!(>%!-4%!/B!(>%!(-&J!6(&%GBK!-)!(>%!4/)7G%!-&!(>%!5-$(!/B!(>%!-55G6?-(6/!(>-(!(>%!(-&J!$%5$%&%(&L!.-$J6;!(>%!*%;66;!/B!-+!(-&J!6&!-&!&645G%!-&!4-J6;!-!5$/?%)7$%!?-GG!-)!6?G7)6;!(>%!V-G7%&!B/$!.F<TPEK!IC:WFiK!-)!CF..Ei:L!M>%!4-$J6;!(>%!%)!/B!-!(-&JK!+/7!-;-6!4-J%!-!&645G%!5$/?%)7$%!?-GGL!Y%!&7$%!(/!6?G7)%!-GG!5/&&6*G%!%@6(!5/6(&!/B!(>%!4-$J%)!(-&J!6?G7)6;!-+!EsCE#:WFi!&%?(6/&!6!+/7$!?/)%L! BEGIN ilo_task.begin_task(module => Load Transaction Tables, action => Begin overall load, comment => Execution of procedure all_trx_table_loads); // ... code to perform task goes here ilo_task.end_task; EXEPTION WHEN ex_insert_problem THEN ilo_task.end_task(error_num => SQLCODE); WHEN ex_update_problem THEN ilo_task.end_task(error_num => SQLCODE); WHEN others THEN ilo_task.end_task(error_num => SQLCODE); END;MBXBX )%0+#3%#$&WPF!6&!/5%!&/7$?%!&/B(A-$%!-V-6G-*G%!-(!3/7$?%k/$;%L!W(!6&!$%G%-&%)!B$%%!/B!?>-$;%!7)%$!(>%!diT!P%&&%$!d%%$-G!#7*G6?!P6?%&%!_Pd#P`L! E)!/B!?/56%)!6B/$4-(6/L!MB[ &CDD%#$&.#&2.&2H+&<)?&F%!/B!(>%!?//G%&(!(>6;&!-*/7(!(>%!WPF!6&!(>-(!+/7!?-!4/)6B+!6(!(/!6?G7)%!-+!-))6(6/-G!6&($74%(-(6/!B%-(7$%&!+/7!4-+!A-(L!k/$!6&(-?%K!6!?>-5(%$!"1!/B!E@5%$(!F$-?G%!#$-?(6?%&H!F$-?G%!<-(-*-&%!I)466&($-(6/!B$/4!(>%!F-J!:-*G%K!-)!?>-5(%$!"a!/B!#$/!F$-?G%!3OP!_*/(>!B$/4!I5$%&&`K!S/*+!3-)&!6?G7)%&!&/4%!;$%-(!6B/$4-(6/!/!>/A!&>%!>-&!%@(%)%)!(>%!WPF!(/!)/!4/$%!(>-!]7&(!4-$J!>%$!?/45-+U&!?/)%!A6(>!4/)7G%!-)!-?(6/!-4%&L! C>-5(%$!"a!>-&!*%%!$%5$6(%)!-)!6?G7)%)!-(!(>%!%)!/B!(>6&!)/?74%(!B/$!+/7$!$%B%$%?%L!! WUV%!7&%)!WPF!B/$!X76(%!-!A>6G%!-)!>-V%!645G%4%(%)!V-$6/7&!-))^/&!B/$!4+&%GB!-)!B/$!?G6%(&!*7(!%V%$!B/$4-G6[%)!-+(>6;!$%7&-*G%L!S/*+!>-&!)/%!]7&(!(>-(!A6(>!>%$!4/)6B6?-(6/&!(/!WPF!-)!>-&!4-)%!(>/&%!75)-(%&!-V-6G-*G%!-&!5-$(!/B!(>%!&/7$?%!?/)%!)/AG/-)&!B/$!(>%!(A/!*//J&L!W!*%G6%V%!(>%!4/)6B6?-(6/&!-$%!;/6;!(/!%V%(7-GG+!6?/$5/$-(%)!6(/!(>%!*-&%!WPF!5-?J-;%K!*7(!7(6G!(>%+!-$%K!+/7!?-!;%(!(>%4!B$/4!(>%!I5$%&&!*//J!&/7$?%!?/)%!5-;%&L0!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!0 !4))5677"5#$33&.(70((!71(2%-("1>,-$7E<9E!_E@5%$(!#$-?(6?%&`!-)!4))5677"5#$33&.(70((!71(2%-("1>,-$7EF<;/_#$/!F$-?G%!3OP`L!!!! 08! ! ! ! ! ! ! ! ! ! !
  • 21. ! ! ! ! !! !X ()&C=:<*C::F>=&I!-(65-((%$!6&!-!(%?>6X7%K!/$!5-((%$K!(>-(!6&!?/44/G+!7&%)!(/!&/GV%!-!5-$(6?7G-$!5$/*G%4!*7(!/B(%!G%-)&!(/!/(>%$!5$/*G%4&L!37?>!(%?>6X7%&!-$%!(>/7;>(!(/!*%!*%%B6?6-GK!*7(!(>%+!7G(64-(%G+!5$/)7?%!4/$%!6GG!%BB%?(&!(>-!5/&6(6V%!$%&7G(&L!:>%!)6BB%$%?%!*%(A%%!-!-(65-((%$!-)!-!46&(-J%!/$!*-)!5$-?(6?%!6&!(>-(!-!-(65-((%$!>-&!-!$%B-?(/$%)!&/G7(6/!(>-(!?-!*%!)/?74%(%)!-)!5$/V%!(/!5$/V6)%!(>%!)%&6$%)!$%&7G(!4/$%!%BB%?(6V%G+L!! :>%!3OP!-(65-((%$&!(>-(!B/GG/A!-$%!&/4%!/B!(>%!4/&(!B$%X7%(G+!4-)%!46&&(%5&!WUV%!&%%!4-)%L!./&(!/B!(>%4!W!4-)%!4+&%GB!-(!/%!(64%!/$!-/(>%$!-)!(>%$%U&!/!*%((%$!A-+!(/!G%-$!>/A!%()!(/!)/!&/4%(>6;!(>-!(/!&5%)!4-+!>/7$&!4-J6;!75!B/$!/%U&!/A!%$$/$&L!!XB9 ;%I%D+&"#D&0.#6+,&WUV%!&%%!(>6&!B6$&(!-(65-((%$!/V%$!-)!/V%$!(>$/7;>!(>%!+%-$&L!WU4!/B(%!;G-)!(/!&%%!6(!>/A%V%$!-&!6(!;6V%&!4%!-!%-&+!A6!A6(>!-!?G6%(!A>/!>-&!*%?/4%!B$7&($-(%)!A6(>!&/4%!5//$G+!5%$B/$46;!56%?%!/B!3OP!-)!6&!B%%G6;!-(!-!G/&&!B/$!%V%$!B6)6;!-!A-+!(/!645$/V%!6(L!W!?-GG!(>6&!/%!(>%!N)6V6)%!-)!?/X7%$Q!-(65-((%$!*%?-7&%!(>%!&/G7(6/!$%X76$%&!(>-(!+/7!&5G6(!(>%!3OP!&(-(%4%(!6(/!?>7J&!6!/$)%$!(/!/5(646[%!6(L!:>6&!4-+!?$%-(%!4-J%!(>%!3OP!G/;%$K!*7(!6(!A6GG!-G&/!*%!B-&(%$!-)!$%X76$%!G%&&!$%&/7$?%&!(/!%@%?7(%L!! M>%%V%$!-!&6;G%!3OP!&(-(%4%(!?-!*%!7&%)!(/!5$/)7?%!-!$%&7G(K!6(!6&!(>/7;>(!(>6&!6&!5$%B%$-*G%!(/!)/6;!47G(65G%!&(-(%4%(&!-)!?%$(-6G+!6&!*%((%$!(>-!)/6;!$/A^*+^$/A!5$/?%&&6;L!Y7(K!($+6;!(/!)/!%V%$+(>6;!+/7!%%)!(/!)/!6!-!&6;G%K!?/45G%@!&(-(%4%(!?-!-G&/!*%!(>%!$//(!?-7&%!/B!-/(>%$!5$/*G%4H!7&6;!(//!4-+!$%&/7$?%&!(/!5$/)7?%!(>%!$%&7G(!%%)%)L!XB9B9 FQ"/5N+&9]&<#D+Q&G6NN&0"#&!%#^!"Q&?52%/%O"2%.#&! WUV%!&%%!(>6&!B6$&(!%@-45G%!)%4/&($-(%)!-!47G(6(7)%!/B!(64%&K!-)!B/$!(>6&!/%!&5%?6B6?!%@-45G%K!W!(>6J!4/&(!5%/5G%!>-V%!G%-$%)!/(!(/!)/!(>6&L!Y7(K!6(!6&!-!%-&+!A-+!(/!&>/A!>/A!*$%-J6;!3OP!-5-$(!?-!>-V%!-4-[6;!645-?(L!!! M>%!%@%?7(6;!-!-;;$%;-(%!X7%$+!(>-(!%%)&!(/!$%(7$!*/(>!(>%!466474!-)!4-@6474!V-G7%!B/$!-!?/G74K!(>%!?/44/!?>/6?%!6&!(/!%@%?7(%!-!&6;G%!X7%$+!A6(>!(>%!46!-)!4-@!$%(7$%)!-&!B/GG/A&H! SQL> select /* km_min */ min(department_id) from employees ; MIN(DEPARTMENT_ID) ------------------ 10 SQL> @pln km_min SQL_ID 3xfdnnga1pcdf, child number 0 ------------------------------------- Plan hash value: 613773769 ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 1 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | 2 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | ---------------------------------------------------------------------------------------------------------- SQL> SQL> select /* km_max */ max(department_id) from employees ; MAX(DEPARTMENT_ID) ------------------ 110 SQL> @pln km_max! ! ! ! 0"!
  • 22. ! ! ! SQL_ID 9j878bkhc57aj, child number 0 ------------------------------------- Plan hash value: 613773769 ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 1 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | 2 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | ---------------------------------------------------------------------------------------------------------- SQL> SQL> select /* km_min_max */ min(department_id), max(department_id) from employees ; MIN(DEPARTMENT_ID) MAX(DEPARTMENT_ID) ------------------ ------------------ 10 110 SQL> @pln km_min_max SQL_ID 18883amg21pnp, child number 0 ------------------------------------- Plan hash value: 1756381138 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 7 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 7 | | 2 | TABLE ACCESS FULL| EMPLOYEES | 1 | 107 | 107 |00:00:00.01 | 7 | ------------------------------------------------------------------------------------------ SQL> select /* km_split */ 2 (select min(department_id) from employees) min_id, 3 (select max(department_id) from employees) max_id 4 from dual ; MIN_ID MAX_ID --------------- --------------- 10 110 SQL> @pln km_split SQL_ID ad2bpg2z204b5, child number 0 ------------------------------------- Plan hash value: 2189307159 ---------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ---------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 0 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | 2 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | | 3 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | 4 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | | 5 | FAST DUAL | | 1 | 1 | 1 |00:00:00.01 | 0 | ----------------------------------------------------------------------------------------------------------! W!(>6&!?-&%K!(>%!/7(57(!A-&!)%&6$%)!-&!-!&6;G%!$/AK!&/!(>%!(A/!X7%$6%&!-$%!&645G+!A$6((%!-&!(A/!&6;G%^?/G74!&7*^X7%$6%&L!T&6;!-!TiWFi!/B!(>%!(A/!X7%$6%&!A/7G)!>-V%!*%%!-/(>%$!-G(%$-(6V%K!6B!(>%!/7(57(!A-&U(!)%&6$%)!-&!-!&6;G%!$/AL! SQL> select /* km_union */ 2 min(department_id) id 3 from employees 4 union 5 select max(department_id) 6 from employees; ID --------------- 10 110 SQL> @pln km_union!! 00! ! ! ! ! ! ! ! ! ! !
  • 23. ! ! ! ! !! ! SQL_ID cvgw7gu0r4w62, child number 0 ------------------------------------- Plan hash value: 1280351157 --------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name |Starts |E-Rows |A-Rows | A-Time |Buffers | OMem | 1Mem | Used-Mem | --------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 2 | | | | | 1 | SORT UNIQUE | | 1 | 2 | 2 |00:00:00.01 | 2 | 2048 | 2048 | 2048 (0)| | 2 | UNION-ALL | | 1 | | 2 |00:00:00.01 | 2 | | | | | 3 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | | | | 4 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | | | | | 5 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 1 | | | | | 6 | INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX | 1 | 1 | 1 |00:00:00.01 | 1 | | | | ---------------------------------------------------------------------------------------------------------------------------------!! :/!$%B-?(/$!(>%!X7%$+!(>6&!A-+!4-J%&!&%&%K!)/%&U(!6(R!F$-?G%!A6GG!7&%!(>%!5$/5%$!.Wi=.Is!/5(646[-(6/!/B!(>%!6)%@!B7GG!&?-K!*7(!/G+!6B!(>%!X7%$+!%%)&!/%!-;;$%;-(%!V-G7%!B/$!%6(>%$!(>%!46!/$!4-@!-(!-!(64%L!WB!+/7!%%)!*/(>K!(>%!/5%$-(6/!$%V%$(&!(/!-!5/&&6*G+!?/&(G+!B7GG!(-*G%!&?-L!<6V6)6;!(>%!X7%$+!6(/!(A/!&%5-$-(%!X7%$6%&!-GG/A&!+/7!(/!;%(!(>%!$%&7G(!+/7!A-(!A6(>!4664-G!$%&/7$?%!7&%L!XB9B7 FQ"/5N+&7]&CNN&.,&#.#+&! :>6&!%@-45G%!&>/A&!-!&G6;>(G+!)6BB%$%(!A-+!6!A>6?>!(>%!N)6V6)%!-)!?/X7%$Q!-(65-((%$!/??7$&L!W!(>6&!?-&%K!-!&6;G%!X7%$+!6&!7&%)!(/!$%($6%V%!)-(-!*7(!-!5$%)6?-(%!6&!5$%&%(!(>-(!5$/V6)%&!-!%6(>%$=/$!&6(7-(6/L!M>-(!W!4%-!*+!(>-(!6&!(>-(!B/$!&/4%!B6G(%$!V-G7%&K!(>%!X7%$+!A6GG!%%)!(/!$%(7$!-GG!$/A&!-)!B/$!/(>%$!B6G(%$!V-G7%&K!(>%!X7%$+!A6GG!$%(7$!-!G646(%)!&7*&%(L!! :>%$%!6&!/%!/(>%$!?/)6(6/!(>-(!47&(!*%!4%(!B/$!(>6&!-(65-((%$!(/!*%!4-(?>%)L!:>%!B6G(%$!V-G7%!(>-(!6&!(>%!)%(%$46%$!B/$!$%(7$6;!-GG!$/A&!/$!5-$(6-G!$/A&!6&U(!6!(>%!(-*G%!B$/4!A>6?>!+/7!A-(!(/!$%(7$!(>%!$/A&L!:>6&!4-+!&/7)!-!*6(!?/B7&6;!&/!G%(U&!G//J!-(!-!%@-45G%L! SELECT /* korig */ cd.cust_sys_id, cd.clup_sys_id FROM td_clup_detail_mv cd JOIN td_row_level_security_mv rl ON cd.clup_sys_id = rl.clup_sys_id JOIN td_individual_mv i ON rl.user_sys_id = i.indiv_sys_id WHERE doc_type_cd IN (AGENCY, FNAS-LNR) AND agent_stat_cd = ACTIVE AND i.user_login_id = Reporting ! I&!+/7!?-!&%%K!(>%!/G+!(-*G%!A%!A-(!$/A&!B$/4!6&!:<jCPT#j<E:IWPj.gL!Y7(K!6!/$)%$!(/!)%(%$46%!A>6?>!$/A&!(/!$%(7$K!(>%$%!6&!-!]/6!(/!-!&%?7$6(+!(-*G%L!:>%!$/A&!6!(>%!&%?7$6(+!(-*G%!(>-(!-$%!-V-6G-*G%!-$%!)%(%$46%)!*+!(>%!B6G(%$!-;-6&(!7&%$jG/;6j6)L!C%$(-6!7&%$&K!*-&%)!/!(>%6$!-7(>/$6[-(6/!G%V%GK!-$%!-*G%!(/!-??%&&!-GG!)-(-!A>6G%!/(>%$!7&%$&!A6GG!*%!$%&($6?(%)!(/!/G+!-!&4-GG%$!&7*&%(!/B!)-(-L!:>%!(-*G%!?/(-66;!(>6&!-7(>/$6[-(6/!?/)%!6&!:<jWi<WgW<TIPj.gL!W!(>%!X7%$+K!(>%!7&%$U&!G/;6!6)!6&!7&%)!(/!$%($6%V%!(>%!$/A&!B$/4!(>%!&%?7$6(+!(-*G%L!Y7(K!>%$%U&!A>%$%!(>%!6&&7%!5/5&!75L!M>-(!6B!(>%!7&%$!6&!7$%&($6?(%)!-)!?-!&%%!-GG!(>%!)-(-R!W!(>-(!?-&%K!+/7!-$%!$%-)6;!5/(%(6-GG+!(>/7&-)&!/B!$/A&!6!(>%!&%?7$6(+!(-*G%!(>-(!)/U(!%%)!(/!*%!$%-)L!IGG!+/7!$%-GG+!%%)!(/!)/!6&!(/!$%-)!(>%!(-*G%!B$/4!A>6?>!+/7!%%)!(/!$%($6%V%!$/A&L! :>%!%@%?7(6/!5G-!&>/A&!+/7!(>%!A/$J!$%X76$%)!(/!$%-)!(>%!&%?7$6(+!(-*G%L! SQL> @pln korig SQL_ID bjasak8wj3q9v, child number 0 ------------------------------------- Plan hash value: 1846763385 ------------------------------------------------------------------------------------------------------------------------------------! ! ! ! 01!
  • 24. ! ! ! | Id | Operation | Name |Starts |A-Rows | A-Time |Buffers |OMem |1Mem |Used-Mem | ------------------------------------------------------------------------------------------------------------------------------------ |* 1 | HASH JOIN | | 1 | 20908 |00:00:23.46 | 55968 |4042K|1659K|6226K (0)| | 2 | MAT_VIEW ACCESS BY INDEX ROWID | TD_ROW_LEVEL_SECURITY_MV | 1 | 118K|00:00:22.45 | 53856 | | | | | 3 | NESTED LOOPS | | 1 | 118K|00:00:00.24 | 136 | | | | | 4 | MAT_VIEW ACCESS BY INDEX ROWID| TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01 | 3 | | | | |* 5 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01 | 2 | | | | |* 6 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N1| 1 | 118K|00:00:00.17 | 133 | | | | |* 7 | VIEW | index$_join$_001 | 1 | 20908 |00:00:00.71 | 2112 | | | | |* 8 | HASH JOIN | | 1 | 20908 |00:00:00.68 | 2112 |1636K|1091K|2215K (0)| |* 9 | HASH JOIN | | 1 | 20908 |00:00:00.28 | 173 |2587K|1183K|3910K (0)| |* 10 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N3 | 1 | 47734 |00:00:00.01 | 61 | | | | | 11 | INLIST ITERATOR | | 1 | 88001 |00:00:00.09 | 112 | | | | |* 12 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N14 | 2 | 88001 |00:00:00.01 | 112 | | | | |* 13 | INDEX FAST FULL SCAN | TD_CLUP_DETAIL_MV_IDX1 | 1 | 88001 |00:00:00.18 | 1939 | | | | ------------------------------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("CD"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 5 - access("I"."USER_LOGIN_ID"=Reporting) 6 - access("RL"."USER_SYS_ID"="I"."INDIV_SYS_ID") 7 - filter(("CD"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("CD"."DOC_TYPE_CD"))) 8 - access(ROWID=ROWID) 9 - access(ROWID=ROWID) 10 - access("CD"."AGENT_STAT_CD"=ACTIVE) 12 - access(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) 13 - filter(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) ! W!(>6&!?-&%K!(>%!7&%$!A-&!7$%&($6?(%)L!WB!(>%!7&%$!A-&!$%&($6?(%)K!(>%!645-?(!/B!>6((6;!(>%!&%?7$6(+!(-*G%!A/7G)U(!*%!X76(%!&/!*-)K!*%?-7&%!/G+!-!G646(%)!74*%$!/B!$/A&!A6GG!%%)!(/!*%!&%G%?(%)!B$/4!6(!-&!B/GG/A&H! SQL> @pln korig2 SQL_ID 5zuyphy3v87rm, child number 0 ------------------------------------- Plan hash value: 1846763385 --------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name |Starts |A-Rows | A-Time |Buffers |OMem |1Mem | --------------------------------------------------------------------------------------------------------------------------- |* 1 | HASH JOIN | | 1 | 1199 |00:00:00.71 | 10908 |1245K|1245K| | 2 | MAT_VIEW ACCESS BY INDEX ROWID | TD_ROW_LEVEL_SECURITY_MV | 1 | 11507 |00:00:00.12 | 10106 | | | | 3 | NESTED LOOPS | | 1 | 11509 |00:00:00.02 | 18 | | | | 4 | MAT_VIEW ACCESS BY INDEX ROWID| TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01 | 3 | | | |* 5 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01 | 2 | | | |* 6 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N1 | 1 | 11507 |00:00:00.02 | 15 | | | |* 7 | VIEW | index$_join$_001 | 1 | 20908 |00:00:00.53 | 802 | | | |* 8 | HASH JOIN | | 1 | 20908 |00:00:00.51 | 802 |1636K|1091K| |* 9 | HASH JOIN | | 1 | 20908 |00:00:00.28 | 173 |2587K|1183K| |* 10 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N3 | 1 | 47734 |00:00:00.01 | 61 | | | | 11 | INLIST ITERATOR | | 1 | 88001 |00:00:00.09 | 112 | | | |* 12 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N14 | 2 | 88001 |00:00:00.01 | 112 | | | |* 13 | INDEX FAST FULL SCAN | KM_TD_CLUP_DETAIL_MV_IDX1 | 1 | 88001 |00:00:00.09 | 629 | | | --------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("CD"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 5 - access("I"."USER_LOGIN_ID"=e.grady@xxx.com) 6 - access("RL"."USER_SYS_ID"="I"."INDIV_SYS_ID") 7 - filter(("CD"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("CD"."DOC_TYPE_CD"))) 8 - access(ROWID=ROWID) 9 - access(ROWID=ROWID) 10 - access("CD"."AGENT_STAT_CD"=ACTIVE) 12 - access(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) 13 - filter(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR))!!! 0! ! ! ! ! ! ! ! ! ! !
  • 25. ! ! ! ! !! ! :>%!$%B-?(/$%)!&/G7(6/!A/7G)!%%)!(/!5$/V6)%!-!A-+!(/!)%(%$46%!(>%!-??%&&!G%V%G!-)!/G+!%@%?7(%!(>%!]/6!(/!(>%!&%?7$6(+!(-*G%!6B!(>%!7&%$U&!-7(>/$6[-(6/!G%V%G!A-&!$%&($6?(%)!-)!*+5-&&!]/66;!(/!(>-(!(-*G%!6B!(>%!7&%$!A-&!7$%&($6?(%)L!:>%!&/G7(6/!6&H! WITH /* krewrite */ access_lvl as ( SELECT row_access_auth_cd, indiv_sys_id FROM td_individual_mv WHERE user_login_id = Reporting ) SELECT c.cust_sys_id, c.clup_sys_id FROM td_clup_detail_mv c, access_lvl a WHERE c.doc_type_cd IN (AGENCY, FNAS-LNR) AND c.agent_stat_cd = ACTIVE AND a.row_access_auth_cd = RESTRICTED AND c.clup_sys_id in (select rl.clup_sys_id from td_row_level_security_mv rl where rl.user_sys_id = a.indiv_sys_id) UNION ALL SELECT c.cust_sys_id, c.clup_sys_id FROM td_clup_detail_mv c, access_lvl a WHERE c.doc_type_cd IN (AGENCY, FNAS-LNR) AND c.agent_stat_cd = ACTIVE AND a.row_access_auth_cd = UNRESTRICTED SQL> @pln krewrite SQL_ID ghkvzdsb9d38w, child number 0 ------------------------------------- Plan hash value: 1290605034 ---------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts |A-Rows | A-Time |Buffers |Reads | OMem | 1Mem | ---------------------------------------------------------------------------------------------------------------------------------------- | 1 | TEMP TABLE TRANSFORMATION | | 1 | 20908 |00:00:00.34 | 4763 | 1 | | | | 2 | LOAD AS SELECT | | 1 | 1 |00:00:00.05 | 7 | 0 | 265K| 265K| | 3 | MAT_VIEW ACCESS BY INDEX ROWID | TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01 | 3 | 0 | | | |* 4 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01 | 2 | 0 | | | | 5 | UNION-ALL | | 1 | 20908 |00:00:00.27 | 4753 | 1 | | | |* 6 | HASH JOIN | | 1 | 0 |00:00:00.01 | 6 | 1 | 733K| 733K| | 7 | NESTED LOOPS | | 1 | 0 |00:00:00.01 | 6 | 1 | | | |* 8 | VIEW | | 1 | 0 |00:00:00.01 | 6 | 1 | | | | 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6E18_BE82C8E3 | 1 | 1 |00:00:00.01 | 6 | 1 | | | | 10 | SORT UNIQUE | | 0 | 0 |00:00:00.01 | 0 | 0 |73728 |73728 | | 11 | MAT_VIEW ACCESS BY INDEX ROWID| TD_ROW_LEVEL_SECURITY_MV | 0 | 0 |00:00:00.01 | 0 | 0 | | | |* 12 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N1 | 0 | 0 |00:00:00.01 | 0 | 0 | | | |* 13 | VIEW | index$_join$_002 | 0 | 0 |00:00:00.01 | 0 | 0 | | | |* 14 | HASH JOIN | | 0 | 0 |00:00:00.01 | 0 | 0 | 991K| 991K| |* 15 | HASH JOIN | | 0 | 0 |00:00:00.01 | 0 | 0 | 1088K| 1088K| |* 16 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N3 | 0 | 0 |00:00:00.01 | 0 | 0 | | | | 17 | INLIST ITERATOR | | 0 | 0 |00:00:00.01 | 0 | 0 | | | |* 18 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N14 | 0 | 0 |00:00:00.01 | 0 | 0 | | | |* 19 | INDEX FAST FULL SCAN | KM_TD_CLUP_DETAIL_MV_IDX1 | 0 | 0 |00:00:00.01 | 0 | 0 | | | | 20 | MERGE JOIN CARTESIAN | | 1 | 20908 |00:00:00.25 | 4747 | 0 | | | |* 21 | VIEW | | 1 | 1 |00:00:00.01 | 3 | 0 | | | | 22 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6E18_BE82C8E3 | 1 | 1 |00:00:00.01 | 3 | 0 | | | | 23 | BUFFER SORT | | 1 | 20908 |00:00:00.23 | 4744 | 0 | 1328K| 528K| |* 24 | MAT_VIEW ACCESS FULL | TD_CLUP_DETAIL_MV | 1 | 20908 |00:00:00.19 | 4744 | 0 | | | ---------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("USER_LOGIN_ID"=Reporting) 6 - access("C"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 8 - filter("A"."ROW_ACCESS_AUTH_CD"=RESTRICTED) 12 - access("RL"."USER_SYS_ID"="A"."INDIV_SYS_ID") 13 - filter(("C"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("C"."DOC_TYPE_CD"))) 14 - access(ROWID=ROWID) 15 - access(ROWID=ROWID) 16 - access("C"."AGENT_STAT_CD"=ACTIVE) 18 - access(("C"."DOC_TYPE_CD"=AGENCY OR "C"."DOC_TYPE_CD"=FNAS-LNR)) 19 - filter(("C"."DOC_TYPE_CD"=AGENCY OR "C"."DOC_TYPE_CD"=FNAS-LNR)) 21 - filter("A"."ROW_ACCESS_AUTH_CD"=UNRESTRICTED) 24 - filter(("C"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("C"."DOC_TYPE_CD")))! ! ! ! 0a!
  • 26. ! ! ! SQL> @pln krewrite3 SQL_ID cwuw5ccd5v0dz, child number 0 ------------------------------------- Plan hash value: 2804591148 ------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name |Starts |A-Rows | A-Time |Buffers |Reads |OMem |1Mem | ------------------------------------------------------------------------------------------------------------------------------------- | 1 | TEMP TABLE TRANSFORMATION | | 1 | 1199 |00:00:01.09 | 10925 | 15 | | | | 2 | LOAD AS SELECT | | 1 | 1 |00:00:00.01 | 7 | 1 | 265K| 265K| | 3 | MAT_VIEW ACCESS BY INDEX ROWID | TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01 | 3 | 1 | | | |* 4 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01 | 2 | 1 | | | | 5 | UNION-ALL | | 1 | 1199 |00:00:01.07 | 10915 | 14 | | | |* 6 | HASH JOIN | | 1 | 1199 |00:00:01.07 | 10912 | 14 |1238K|1100K| | 7 | NESTED LOOPS | | 1 | 11507 |00:00:00.46 | 10110 | 14 | | | |* 8 | VIEW | | 1 | 1 |00:00:00.01 | 6 | 1 | | | | 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6E23_BE82C8E3 | 1 | 1 |00:00:00.01 | 6 | 1 | | | | 10 | SORT UNIQUE | | 1 | 11507 |00:00:00.45 | 10104 | 13 | 690K| 433K| | 11 | MAT_VIEW ACCESS BY INDEX ROWID| TD_ROW_LEVEL_SECURITY_MV | 1 | 11507 |00:00:00.41 | 10104 | 13 | | | |* 12 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N1 | 1 | 11507 |00:00:00.17 | 15 | 13 | | | |* 13 | VIEW | index$_join$_002 | 1 | 20908 |00:00:00.55 | 802 | 0 | | | |* 14 | HASH JOIN | | 1 | 20908 |00:00:00.53 | 802 | 0 |1895K|1011K| |* 15 | HASH JOIN | | 1 | 20908 |00:00:00.28 | 173 | 0 |2587K|1183K| |* 16 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N3 | 1 | 47734 |00:00:00.01 | 61 | 0 | | | | 17 | INLIST ITERATOR | | 1 | 88001 |00:00:00.09 | 112 | 0 | | | |* 18 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N14 | 2 | 88001 |00:00:00.01 | 112 | 0 | | | |* 19 | INDEX FAST FULL SCAN | KM_TD_CLUP_DETAIL_MV_IDX1 | 1 | 88001 |00:00:00.09 | 629 | 0 | | | | 20 | MERGE JOIN CARTESIAN | | 1 | 0 |00:00:00.01 | 3 | 0 | | | |* 21 | VIEW | | 1 | 0 |00:00:00.01 | 3 | 0 | | | | 22 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6E23_BE82C8E3 | 1 | 1 |00:00:00.01 | 3 | 0 | | | | 23 | BUFFER SORT | | 0 | 0 |00:00:00.01 | 0 | 0 |1249K| 518K| |* 24 | MAT_VIEW ACCESS FULL | TD_CLUP_DETAIL_MV | 0 | 0 |00:00:00.01 | 0 | 0 | | | ------------------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("USER_LOGIN_ID"=e.grady@xxx.com) 6 - access("C"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 8 - filter("A"."ROW_ACCESS_AUTH_CD"=RESTRICTED) 12 - access("RL"."USER_SYS_ID"="A"."INDIV_SYS_ID") 13 - filter(("C"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("C"."DOC_TYPE_CD"))) 14 - access(ROWID=ROWID) 15 - access(ROWID=ROWID) 16 - access("C"."AGENT_STAT_CD"=ACTIVE) 18 - access(("C"."DOC_TYPE_CD"=AGENCY OR "C"."DOC_TYPE_CD"=FNAS-LNR)) 19 - filter(("C"."DOC_TYPE_CD"=AGENCY OR "C"."DOC_TYPE_CD"=FNAS-LNR)) 21 - filter("A"."ROW_ACCESS_AUTH_CD"=UNRESTRICTED) 24 - filter(("C"."AGENT_STAT_CD"=ACTIVE AND INTERNAL_FUNCTION("C"."DOC_TYPE_CD"))) ! :>%!$%&7G(!/B!(>%!$%B-?(/$%)!&/G7(6/!6&!(>-(!+/7!;%(!-!&6;G%!5G-!(>-(!A/$J&!A%GG!B/$!*/(>!(+5%&!/B!7&%$&L!:>%!/$6;6-G!3OP!A/7G)!5$/V6)%!B-&(%$!$%&5/&%!(64%&!B/$!7&%$&!A6(>!$%&($6?(%)!-??%&&!*7(!A/7G)!*%!&G/A!6!?/45-$6&/!B/$!7&%$&!A6(>!7$%&($6?(%)!-??%&&L!! ,%%5!6!46)!(>-(!(>%!N)6V6)%!-)!?/X7%$Q!-(65-((%$!?-!?/4%!6!4-+!BG-V/$&L!:>%!J%+!6&!(/!)%(%$46%!6B!(>%!$%X76$%)!A/$J!?-!*%!&5G6(!75!6!&7?>!-!A-+!-&!(/!-GG/A!?/45%(6;!%%)&!(/!*%!4%(L!:>%!(A/!%@-45G%&!A%UV%!$%V6%A%)!-$%!]7&(!(>%!(65!/B!(>%!6?%*%$;L!Z/7UGG!G6J%G+!B6)!4/$%!A-+&!(>6&!-(65-((%$!A6GG!4-6B%&(!6!+/7$!3OP!6B!+/7!)6;!)%%5%$!A6(>!-!N)6V6)%!-)!?/X7%$Q!%+%L!XB7 :H+&E"2N%#$&E6#&:>%!Nd-(G6;!;7Q!-(65-((%$!6&!%V6)%?%)!*+!$%5%-(%)!-??%&&!(/!/*]%?(&!(>-(!&>/7G)!/G+!%%)!(/!*%!-??%&&%)!/?%L!P6J%!-!-?(7-G!d-(G6;!;7K!(>6&!-(65-((%$!?-!J6GG!5%$B/$4-?%!A6(>!$%5%-(%)K!$-56)^B6$%!/*]%?(!-??%&&%&L!:>%$%!-$%!4-+!BG-V/$&!/B!(>6&!-(65-((%$K!*7(!W!&%%!6(!4/&(!B$%X7%(G+!$%5%-(%)!7&%!/B!&7*X7%$6%&!(>-(!?/457(%!-;;$%;-(%!V-G7%&L!!! 0D! ! ! ! ! ! ! ! ! ! !
  • 27. ! ! ! ! !! !XB7B9 FQ"/5N+]&>+5+"2%#$&"$$,+$"2+3& .-+!-55G6?-(6/&!%%)!(/!B6)!$/A&!/B!)-(-!(>-(!4-(?>!-!?/)6(6/!*-&%)!/!-;;$%;-(6;!)-(-!6!(>%!(-*G%!6!/$)%$!(/!;%(!-!V-G7%!(/!?/45-$%!(/!%-?>!$/A!(/!)%(%$46%!6B!(>%!$/A!&>/7G)!*%!6?G7)%)!6!(>%!$%&7G(!&%(L!:>%!%@-45G%!A%U$%!;/6;!(/!$%V6%A!6&!(+56?-GG+!&%%!A>%!+/7$!X7%$+!%%)&!(/!B6)!$/A&!(>-(!4-(?>!-!N-&!/BQ!)-(%L! W!(>6&!?-&%K!(>%!%V6$/4%(!A-&!-!46@!/B!FP:#!-)!/G6%!$%5/$(6;!X7%$6%&L!.-+!/B!(>%!$%5/$(6;!X7%$6%&!A/7G)!(-J%!>/7$&!(/!?/45G%(%!-)!(>6&!-)V%$&%G+!-BB%?(%)!FP:#!$%&5/&%!(64%&L!:>%!B/GG/A6;!$%5/$(6;!X7%$+!(//J!/V%$!!>/7$&!(/!$%(7$!]7&(!/V%$!"eK888!$/A&L!M/Af!! SELECT ATTRITION_FCTR, ATTRITION_FACTOR_CLNDR_YR, ATTRITION_FACTOR_CLNDR_MO, PGRD_PROJECT_CODE FROM ODS_PGRD_PROJECT_ATRTN_FACTORS A WHERE SIMULATION_CLNDR_YR || SIMULATION_CLNDR_MO = (SELECT MAX(B.SIMULATION_CLNDR_YR || B.SIMULATION_CLNDR_MO) FROM ODS_PGRD_PROJECT_ATRTN_FACTORS B WHERE A.PGRD_PROJECT_CODE = B.PGRD_PROJECT_CODE) :>%!$%&5/&%!(64%!5$/B6G%!-)!%@%?7(6/!5G-!&>/A%)!-GG!(>%!(64%!&5%(!6!B%(?>6;!$/A&L! -- Profile (R = 4 hours 14 minutes 4.236 seconds) DB Call Duration CPU Other %R Rows LIO PIO ------------- ---------- ---------- ------- ----- ------ ---------- ---------- FETCH 15,238.249 15,297.950 -59.701 100% 18,480 52,756,900 38,490,001 Between Calls 5.943 0.000 5.943 0% 0 0 0 PARSE 0.032 0.030 0.002 0% 0 0 0 EXEC 0.012 0.000 0.012 0% 0 3 1 ------------- ---------- ---------- ------- ----- ------ ---------- ---------- Total 15,244.236 15,297.980 -53.744 100% 18,480 52,756,903 38,490,002 -- Execution Plan ID Row Source Operation Duration %R Rows LIO PIO -- ----------------------------------- ---------- ------ ---------- ---------- ---------- 1 FILTER -123.167 -0.8% 18,480 86,529 0 2 TABLE ACCESS FULL OBJ#(32390) 1.526 0.0% 271,830 3,053 7,588 3 SORT AGGREGATE 0.761 0.0% 28,843 0 0 4 SORT AGGREGATE 96.790 0.6% 28,843 0 0 5 TABLE ACCESS FULL OBJ#(32390) 15,093.126 100.2% 14,816,070 52,667,318 38,482,413 -- ----------------------------------- ---------- ------ ---------- ---------- ---------- 15,069.036 100.0% 52,756,900 38,490,001! :>%!5G-!&>/A&!(A/!B7GG!(-*G%!&?-!/5%$-(6/&!/!(>%!F<3j#dS<j#SFbEC:jI:S:ijkIC:FS3!(-*G%L!WB!+/7!G//J!-(!(>%!X7%$+K!+/7UGG!/(6?%!(>-(!(>%!5$%)6?-(%!?/(-6&!-!&7*^X7%$+!(/!?>%?J!B/$!(>%!4-@!)-(%!B/$!(>%!5$/]%?(!*-&%)!/!(>%!5$/]%?(!?/)%!B$/4!(>%!?7$$%(!5$/]%?(L!:>%$%!-$%!(A/!5$/*G%4&L!! k6$&(K!(>%!(-*G%!>-&!0c"Ke18!$/A&K!&/!B/$!%-?>!$/AK!(>%!&7*^X7%$+!4-+!%%)!(/!%@%?7(%L!i/(6?%!(>-(!W!&-+!N4-+!%%)!(/!%@%?7(%Q!>%$%L!:>-(U&!*%?-7&%!WU)!&7&5%?(!(>%!X7%$+!A6GG!*%%B6(!B$/4!&/4%!&7*^X7%$+!?-?>6;!-)!/(!$%-GG+!>-V%!(/!%@%?7(%!(>%!X7%$+!/V%$!-)!/V%$!B/$!$%5%-(%)!V-G7%&L!Y7(K!%-?>!(64%!6(!)/%&!%@%?7(%K!6(!A6GG!$%X76$%!-!B7GG!(-*G%!&?-L!W(!&%%4&!(>-(!6B!-!6)%@!/!#dS<j#SFbEC:jCF<E!_-)!3W.TPI:WFijCPi<SjZS!-)!3W.TPI:WFijCPi<Sj.F`!A-&!-V-6G-*G%K!(>%!X7%$+!A/7G)!*%%B6(!*+!-(!G%-&(!*%6;!-*G%!(/!7&%!(>%!6)%@!(/!;%(!(>%!4-@!V-G7%L!:>%!$%-&/!6(!A-&U(!(>%$%!A-&!(>-(!(>%+!>-)!-!$7G%!(>-(!(>%+!/G+!?$%-(%!&6;G%!?/G74!6)%@%&L!W!*%G6%V%!(>6&!A-&!-!>/G)/V%$!B$/4!A>%!(>%!)-(-*-&%!A-&!/G+!7&%)!B/$!FP:#!-)!-!B%A!/(>%$!N;//)Q!$%-&/&K!*7(!(>6&!$7G%!A-&!5$/>6*6(6;!(>%4!B$/4!/5(646[6;!/(!/G+!(>6&!3OPK!*7(!G/(&!4/$%!-&!A%GGL! :>%!&%?/)!5$/*G%4!6&!)7%!(/!(>%!&-4%!&7*^X7%$+L!:>%!47G(65G%!%@%?7(6/&!/B!(>%!3EPEC:!.Is!X7%$+!4%-(!47G(65G%!V6&6(&!(/!(>%!&-4%!(-*G%!)$6V6;!(>%!X7%$+L!EV%!6B!(>%!6)%@!>-)!*%%!6!5G-?%K!(>%!$%5%-(%)!! ! ! ! 0c!
  • 28. ! ! !V6&6(&!(/!(>%!&-4%!/*]%?(!4%-&!(>-(!(>%!&-4%!*G/?J&!A6GG!%%)!(/!*%!($-V%$&%)!/V%$!-)!/V%$L!M>+!/(!($-V%$&%!(>%!*G/?J&!]7&(!/?%R! :>6&!A-&!-!?>-;%!A%!?/7G)!645G%4%(f!W!/$)%$!(/!?>-;%!(>%!X7%$+!(/!4-J%!-!&6;G%!5-&&!/V%$!(>%!(-*G%!A>6G%!-GG/A6;!(>%!4-@!?/45-$6&/!(/!*%!>-)G%)K!A%!&645G+!$%A$/(%!(>%!X7%$+!(/!7&%!-!--G+(6?!.Is!-&!B/GG/A&H! SELECT a.ATTRITION_FCTR, a.ATTRITION_FACTOR_CLNDR_YR, a.ATTRITION_FACTOR_CLNDR_MO, a.PGRD_PROJECT_CODE FROM ( SELECT MAX(simulation_clndr_yr || simulation_clndr_mo) over (partition by pgrd_project_code) as the_max, ATTRITION_FCTR, ATTRITION_FACTOR_CLNDR_YR, ATTRITION_FACTOR_CLNDR_MO, PGRD_PROJECT_CODE, SIMULATION_CLNDR_YR || SIMULATION_CLNDR_MO as the_yrmo FROM ODS_PGRD_PROJECT_ATRTN_FACTORS ) a WHERE a.the_yrmo = a.the_max ;! Y+!$%B-?(/$6;!(>%!3OP!(/!4-J%!-!&6;G%!5-&&!/V%$!(>%!(-*G%!-)!?/457(%!(>%!.Is!V-G7%!-&!-!&%5-$-(%!?/G74!7&6;!(>%!--G+(6?K!A%!A%$%!-*G%!(/!-V/6)!$%5%-(%)!-??%&&%&!(/!(>%!(-*G%!-)!$%)7?%!(>%!A/$J!$%X76$%)!(/!]7&(!-!B$-?(6/!/B!(>%!/$6;6-GL! -- Profile (R = 16.989 seconds) DB Call Duration CPU Other %R Rows LIO PIO ------------- -------- ------- ------- ----- ------ ----- ----- FETCH 11.662 11.110 0.552 68.6% 18,480 1,828 4,680 Between Calls 5.030 0.000 5.030 29.6% 0 0 0 EXEC 0.272 0.030 0.242 1.6% 0 3 1 PARSE 0.026 0.030 -0.004 0.2% 0 6 0 ------------- -------- ------- ------- ----- ------ ----- ----- Total 16.989 11.170 5.819 100% 18,480 1,837 4,681 -- Execution Plan ID Row Source Operation Duration %R Rows LIO PIO/R PIO/W -- ----------------------------------- ---------- ------ ------- ----- ----- ----- 1 VIEW 1.742 15.2% 18,480 0 0 0 2 WINDOW SORT 8.127 70.9% 271,830 7 2,861 1,340 3 TABLE ACCESS FULL OBJ#(32390) 1.598 13.9% 271,830 1,826 1,819 0 -- ----------------------------------- ---------- ------ ------- ----- ----- ----- 11.467 100.0% 1,833 4,680 1,340! k$/4!-G4/&(!!>/7$&!"a!467(%&!)/A!(/!]7&(!7)%$!"c!&%?/)&L!IA%&/4%f!I)K!(>%+!A%$%!%V%!)/7*G+!>-55+!(>-(!(>6&!?/7G)!*%!)/%!A6(>/7(!>-V6;!(/!?$%-(%!-+!6)%@%&L!!XBM >+_%#I+#2%#$&2H+&KH++N&:>6&!-(65-((%$!6&!6!7&%!A>%!-!3OP!&(-(%4%(!>-&!*%%!A$6((%!(/!5$/V6)%!&/4%!B7?(6/-G6(+!(>-(!6&!-V-6G-*G%!6!-!*76G(^6!B7?(6/L!WU4!/(!&7$%!A>-(!6(!6&!-*/7(!)-(%!4-(>!(>-(!&%%4&!(/!*%!(>%!5$64-$+!?7G5$6(!B/$!(>6&K!*7(!W!&%%4!(/!?/4%!-?$/&&!-!G/(!/B!G%;(>+!?/)%!(>-(!?/7G)!*%!$%5G-?%)!*+!-!&>/$(!-)!&645G%!*76G(^6!B%-(7$%L!!XBMB9 FQ"/5N+]&A6,,+#2&W,^*,%.,&W,&`",%"#0+&>+5.,2& W!A-&!>-)%)!-!B-6$G+!G%;(>+!-)!?/45G%@!G//J6;!3OP!&(-(%4%(!(>-(!(+56?-GG+!%@%?7(%)!6!(>%!a^"8!467(%!$-;%L!:>%!/G6%!$%5/$(6;!(//G!>-)!-!a!467(%!(64%/7(!G646(!&%(!&7?>!(>-(!-+!$%5/$(!(>-(!(//J!G/;%$!(>-!a!467(%&!(/!?/45G%(%!A/7G)!*%!?-?%GG%)!-)!(>%!7&%$!A/7G)!*%!$%X76$%)!(/!&?>%)7G%!(>%!]/*!(/!*%!!! 0e! ! ! ! ! ! ! ! ! ! !
  • 29. ! ! ! ! !! !?/45G%(%)!6!/BB^5%-J!>/7$&L!!:>%!$%5/$(!A-&!A>-(!&%%4%)!(/!*%!-!B-6$G+!&645G%!G6&(6;!(>-(!&>/A%)!-!?/45-$6&/!/B!(>%!?7$$%(!+%-$^(/^)-(%!$%V%7%!(/!(>%!5$6/$!+%-$U&!$%V%7%!B/$!(>%!&-4%!(64%!-G/;!A6(>!(>%!?/457(%)!Z:<!-)!X7-$(%$G+!V-$6-?%&L!:>%!X7%$+!A-&!%@%?7(%)!V6-!C$+&(-G!S%5/$(&!-)!(>%!/7(57(!B/$4-((%)!*%B/$%!)6&5G-+L!I!(+56?-G!$%&7G(!&%(!B$/4!(>6&!X7%$+!46;>(!G//J!G6J%!(>6&H! ROLLUP_CD CUST_LOC_NM LOC_CITY_NM LOC_REP_NM PRINCIPAL_NM CURR_YR_YTD PRIOR_YR_YTD YTD_VARIANCE QVARIANCE ---------- --------------- ------------------ -------------- ------------------- ----------- ------------ ------------ ---------- CLTIC John Q Public Jacksonville Jay Peterman S. Jacob OBanyon 12356.24 7105.15 5251.09 -3736.5 CTIC John Q Public Jacksonville Jay Peterman S. Jacob OBanyon 93109.05 84158.73 8950.32 -4687.17 FNTIC John Q Public Jacksonville Jay Peterman S. Jacob OBanyon 88757.46 182125.08 -93367.62 -1168.12 CTIC John Q Public Ponte Vedra Beach Winfield Dunn S. Jacob OBanyon 5963.18 2667.05 3296.13 -2897.94 FNTIC John Q Public Ponte Vedra Beach Winfield Dunn S. Jacob OBanyon 0 0 0 0 CLTIC John Q Public Saint Augustine Jay Peterman S. Jacob OBanyon 0 1522.5 -1522.5 0 CTIC John Q Public Saint Augustine Jay Peterman S. Jacob OBanyon 18278.32 25274.69 -6996.37 -2534.61 FNTIC John Q Public Saint Augustine Jay Peterman S. Jacob OBanyon 3907.13 1770.58 2136.55 0 :>%!/7(57(!G//J&!&645G%!%/7;>K!&/!W!A/)%$%)!A>+!6(!A/7G)!(-J%!&/!G/;!(/!?/45G%(%L!F%!G//J!-(!(>%!3OP!-)!W!>-)!4+!-&A%$H! WITH /* k2orig */ curr_period AS (SELECT t3.time_wh_sys_id, t3.acct_period_dt, t3.acct_month_year ,t3.acct_year ,CASE WHEN t3.acct_month IN (1, 2, 3) THEN 1 WHEN t3.acct_month IN (4, 5, 6) THEN 2 WHEN t3.acct_month IN (7, 8, 9) THEN 3 WHEN t3.acct_month IN (10, 11, 12) THEN 4 END curr_qtr FROM tw_dim_time t3 , (SELECT MAX (time_wh_sys_id) time_wh_sys_id FROM tw_dim_time WHERE acct_month_year <= 200912 AND is_acct_end_of_month = 1 AND actual_date < SYSDATE) t WHERE t3.time_wh_sys_id = t.time_wh_sys_id) ,curr_q_periods AS (SELECT CASE curr_period.curr_qtr WHEN 4 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (10) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) WHEN 1 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (1) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) WHEN 2 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (4) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) WHEN 3 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (7) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) END begin_curr_qtr ,CASE curr_period.curr_qtr WHEN 4 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (12) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1)! ! ! ! 0m!
  • 30. ! ! ! WHEN 1 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (3) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) WHEN 2 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (6) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) WHEN 3 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (9) AND t.acct_year = curr_period.acct_year AND t.is_acct_end_of_month = 1) END end_curr_qtr FROM curr_period) ,prior_period AS (SELECT t2.time_wh_sys_id prior_yr_time_sys_id ,t2.acct_month_year prior_yr_period FROM tw_dim_time t2, curr_period WHERE t2.acct_period_dt = ADD_MONTHS (curr_period.acct_period_dt, -12) AND is_acct_end_of_month = 1) ,prior_qtr AS (SELECT DECODE (curr_period.curr_qtr ,1, 4 ,2, 1 ,3, 2 ,4, 3 ) prior_qtr ,DECODE (curr_period.curr_qtr ,1, curr_period.acct_year - 1 ,curr_period.acct_year ) prior_qtr_year FROM curr_period) ,prior_q_periods AS (SELECT CASE pq.prior_qtr WHEN 4 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (10) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 1 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (1) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 2 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (4) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 3 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (7) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) END begin_prior_qtr ,CASE pq.prior_qtr WHEN 4 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (12) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 1 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (3)!! 18! ! ! ! ! ! ! ! ! ! !
  • 31. ! ! ! ! !! ! AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 2 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (6) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) WHEN 3 THEN (SELECT t.acct_month_year FROM tw_dim_time t WHERE t.acct_month IN (9) AND t.acct_year = pq.prior_qtr_year AND t.is_acct_end_of_month = 1) END end_prior_qtr FROM prior_qtr pq) ,time_slices AS (SELECT curr_period.time_wh_sys_id, curr_period.acct_month_year ,curr_period.curr_qtr, prior_period.prior_yr_time_sys_id ,prior_period.prior_yr_period, prior_q_periods.begin_prior_qtr ,prior_q_periods.end_prior_qtr, prior_qtr.prior_qtr ,prior_qtr.prior_qtr_year, curr_q_periods.begin_curr_qtr ,curr_q_periods.end_curr_qtr FROM curr_period ,prior_period ,prior_qtr ,prior_q_periods ,curr_q_periods) ,loc_details AS (SELECT cd.rollup_uw_abbv_cd ,CASE WHEN cd.cust_loc_nm IS NOT NULL AND cd.dba_nm_from_loc_nm_ind = 1 THEN cd.cust_loc_nm WHEN cd.cust_doing_bus_as_nm IS NOT NULL THEN cd.cust_doing_bus_as_nm ELSE cd.cust_bus_nm END cust_loc_nm ,cd.loc_city_nm , cd.loc_rep_f_nm || || cd.loc_rep_mid_int_nm || || cd.loc_rep_l_nm AS loc_rep_nm , (SELECT NVL (con.first_nm, ) || || NVL (con.mid_int_nm, ) || || NVL (con.last_nm, ) || || NVL (con.sufx_nm, ) FROM td_contact_mv con WHERE con.loc_sys_id = cd.loc_sys_id AND UPPER (con.position_type_cd) = PRINCIPAL AND ROWNUM = 1) principal_nm ,cd.clup_sys_id FROM td_clup_detail_mv cd JOIN td_row_level_security_mv rl ON cd.clup_sys_id = rl.clup_sys_id JOIN td_individual_mv i ON rl.user_sys_id = i.indiv_sys_id WHERE cd.doc_type_cd IN (AGENCY, FNAS-LNR) AND cd.cust_sys_id = 5922 AND i.user_login_id = TraxReporting) SELECT DISTINCT rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm ,principal_nm, NVL (SUM (curr_ytd_net), 0) curr_ytd_net ,acct_month_year AS curr_yr_period, curr_qtr ,NVL (SUM (prior_ytd_net), 0) prior_ytd_net, prior_yr_period ,prior_qtr, prior_qtr_year, begin_prior_qtr, end_prior_qtr ,NVL (SUM (prior_q_net_prm.prior_q_net), 0) prior_q_net ,begin_curr_qtr, end_curr_qtr ,NVL (SUM (curr_q_net_prm.curr_q_net), 0) curr_q_net FROM time_slices ,loc_details ,tw_dim_clup clup , (SELECT NVL(SUM (fcm.net_prm_tot_ytd_eom_amt),0) curr_ytd_net! ! ! ! 1"!
  • 32. ! ! ! ,fcm.time_wh_sys_id, fcm.clup_wh_sys_id FROM tw_fact_clup_monthly fcm JOIN time_slices ts ON fcm.time_wh_sys_id = ts.time_wh_sys_id GROUP BY fcm.time_wh_sys_id, fcm.clup_wh_sys_id) curr_ytd_net_prm , (SELECT NVL(SUM (fcm.net_prm_tot_ytd_eom_amt),0) prior_ytd_net ,fcm.time_wh_sys_id, fcm.clup_wh_sys_id FROM tw_fact_clup_monthly fcm JOIN time_slices ts ON fcm.time_wh_sys_id = ts.prior_yr_time_sys_id GROUP BY fcm.time_wh_sys_id, fcm.clup_wh_sys_id) prior_ytd_net_prm , (SELECT NVL (SUM (fcm.net_prm_tot_eom_amt), 0) prior_q_net ,fcm.clup_wh_sys_id FROM tw_fact_clup_monthly fcm JOIN tw_dim_time t5 ON fcm.time_wh_sys_id = t5.time_wh_sys_id JOIN prior_q_periods pq ON t5.acct_month_year BETWEEN pq.begin_prior_qtr AND pq.end_prior_qtr GROUP BY fcm.clup_wh_sys_id) prior_q_net_prm , (SELECT NVL (SUM (fcm.net_prm_tot_eom_amt), 0) curr_q_net ,fcm.clup_wh_sys_id FROM tw_fact_clup_monthly fcm JOIN tw_dim_time t6 ON fcm.time_wh_sys_id = t6.time_wh_sys_id JOIN curr_q_periods cq ON t6.acct_month_year BETWEEN cq.begin_curr_qtr AND cq.end_curr_qtr GROUP BY fcm.clup_wh_sys_id) curr_q_net_prm WHERE loc_details.clup_sys_id = clup.clup_sys_id AND clup.clup_wh_sys_id = curr_ytd_net_prm.clup_wh_sys_id(+) AND clup.clup_wh_sys_id = prior_ytd_net_prm.clup_wh_sys_id(+) AND clup.clup_wh_sys_id = prior_q_net_prm.clup_wh_sys_id(+) AND clup.clup_wh_sys_id = curr_q_net_prm.clup_wh_sys_id(+) GROUP BY rollup_uw_abbv_cd,cust_loc_nm,loc_city_nm,loc_rep_nm,principal_nm,acct_month_year,curr_qtr,prior_yr_period, prior_qtr,prior_qtr_year,begin_prior_qtr,end_prior_qtr,begin_curr_qtr,end_curr_qtr; W!>-(%!(/!7&%!(>-(!47?>!$%-G!%&(-(%!(/!&>/A!+/7!-GG!(>-(K!*7(!W!A-(%)!+/7!(/!;%(!(>%!B7GG!%BB%?(L!WB!+/7!(-J%!(>%!(64%!(/!A-GJ!(>$/7;>!A>-(!(>-(!3OP!6&!($+6;!(/!)/K!+/7UGG!B6)!(>-(!(>%!4-]/$6(+!/B!(>%!?/)%!A-&!5$%&%(!/G+!(/!>-)G%!)%(%$466;!(>%!?7$$%(!-)!5$6/$!+%-$^(/^)-(%!(64%!&G6?%&!-)!(>%!?/457(%!(>%!(/(-G&!%%)%)!A6(>6!%-?>!(64%!&G6?%L!:>%!%@%?7(6/!5G-!&>/A%)!A>%$%!(>%!(64%!A-&!&5%(H! SQL_ID ayp95f5dz662x, child number 0 ------------------------------------- Plan hash value: 1406955805 ---------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name |Starts |A-Rows | A-Time |Buffers |Reads | ---------------------------------------------------------------------------------------------------------------------------------- |* 1 | COUNT STOPKEY | | 3 | 3 |00:00:00.03| 10 | 3 | |* 2 | MAT_VIEW ACCESS BY INDEX ROWID | TD_CONTACT_MV | 3 | 3 |00:00:00.03| 10 | 3 | |* 3 | INDEX RANGE SCAN | TD_CONTACT_MV_FK3 | 3 | 3 |00:00:00.02| 6 | 2 | | 4 | TEMP TABLE TRANSFORMATION | | 1 | 8 |00:04:19.91| 293K| 291K| | 5 | LOAD AS SELECT | | 1 | 1 |00:00:00.01| 27 | 0 | | 6 | NESTED LOOPS | | 1 | 1 |00:00:00.01| 23 | 0 | | 7 | VIEW | | 1 | 1 |00:00:00.01| 20 | 0 | | 8 | SORT AGGREGATE | | 1 | 1 |00:00:00.01| 20 | 0 | |* 9 | TABLE ACCESS BY INDEX ROWID | TW_DIM_TIME | 1 | 216 |00:00:00.01| 20 | 0 | |* 10 | INDEX RANGE SCAN | TW_DIM_TIME_N2 | 1 | 240 |00:00:00.01| 3 | 0 | | 11 | TABLE ACCESS BY INDEX ROWID | TW_DIM_TIME | 1 | 1 |00:00:00.01| 3 | 0 | |* 12 | INDEX UNIQUE SCAN | TW_DIM_TIME_EOM_PK | 1 | 1 |00:00:00.01| 2 | 0 | | 13 | LOAD AS SELECT | | 1 | 1 |00:00:00.01| 50 | 1 | | 14 | VIEW | | 1 | 1 |00:00:00.01| 6 | 1 | | 15 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D31_64822175 | 1 | 1 |00:00:00.01| 6 | 1 | | 16 | LOAD AS SELECT | | 1 | 1 |00:00:00.01| 7 | 0 | | 17 | VIEW | | 1 | 1 |00:00:00.01| 3 | 0 | | 18 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D31_64822175 | 1 | 1 |00:00:00.01| 3 | 0 | | 19 | LOAD AS SELECT | | 1 | 1 |00:00:00.01| 50 | 1 | | 20 | VIEW | | 1 | 1 |00:00:00.01| 6 | 1 | | 21 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D33_64822175 | 1 | 1 |00:00:00.01| 6 | 1 | | 22 | LOAD AS SELECT | | 1 | 1 |00:00:00.01| 45 | 2 |!! 10! ! ! ! ! ! ! ! ! ! !
  • 33. ! ! ! ! !! ! |* 23 | TABLE ACCESS BY INDEX ROWID | TW_DIM_TIME | 1 | 1 |00:00:00.01| 41 | 2 | | 24 | NESTED LOOPS | | 1 | 242 |00:00:00.01| 24 | 2 | | 25 | MERGE JOIN CARTESIAN | | 1 | 1 |00:00:00.01| 21 | 2 | | 26 | MERGE JOIN CARTESIAN | | 1 | 1 |00:00:00.01| 15 | 1 | | 27 | MERGE JOIN CARTESIAN | | 1 | 1 |00:00:00.01| 9 | 0 | | 28 | MERGE JOIN CARTESIAN | | 1 | 1 |00:00:00.01| 6 | 0 | | 29 | VIEW | | 1 | 1 |00:00:00.01| 3 | 0 | | 30 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D31_64822175 | 1 | 1 |00:00:00.01| 3 | 0 | | 31 | BUFFER SORT | | 1 | 1 |00:00:00.01| 3 | 0 | | 32 | VIEW | | 1 | 1 |00:00:00.01| 3 | 0 | | 33 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D31_64822175 | 1 | 1 |00:00:00.01| 3 | 0 | | 34 | BUFFER SORT | | 1 | 1 |00:00:00.01| 3 | 0 | | 35 | VIEW | | 1 | 1 |00:00:00.01| 3 | 0 | | 36 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D33_64822175 | 1 | 1 |00:00:00.01| 3 | 0 | | 37 | BUFFER SORT | | 1 | 1 |00:00:00.01| 6 | 1 | | 38 | VIEW | | 1 | 1 |00:00:00.01| 6 | 1 | | 39 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D34_64822175 | 1 | 1 |00:00:00.01| 6 | 1 | | 40 | BUFFER SORT | | 1 | 1 |00:00:00.01| 6 | 1 | | 41 | VIEW | | 1 | 1 |00:00:00.01| 6 | 1 | | 42 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D32_64822175 | 1 | 1 |00:00:00.01| 6 | 1 | |* 43 | INDEX RANGE SCAN | TW_DIM_TIME_N2 | 1 | 240 |00:00:00.01| 3 | 0 | | 44 | HASH GROUP BY | | 1 | 8 |00:04:19.89| 293K| 291K| |* 45 | HASH JOIN OUTER | | 1 | 11 |00:04:19.89| 293K| 291K| |* 46 | HASH JOIN OUTER | | 1 | 11 |00:04:01.98| 257K| 255K| |* 47 | HASH JOIN OUTER | | 1 | 11 |00:02:23.00| 147K| 147K| |* 48 | HASH JOIN OUTER | | 1 | 11 |00:00:51.74| 45941 | 45832 | | 49 | TABLE ACCESS BY INDEX ROWID | TW_DIM_CLUP | 1 | 11 |00:00:00.10| 103 | 23 | | 50 | NESTED LOOPS | | 1 | 23 |00:00:00.08| 96 | 20 | | 51 | MERGE JOIN CARTESIAN | | 1 | 11 |00:00:00.08| 83 | 20 | | 52 | VIEW | | 1 | 1 |00:00:00.01| 6 | 1 | | 53 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D35_64822175 | 1 | 1 |00:00:00.01| 6 | 1 | | 54 | BUFFER SORT | | 1 | 11 |00:00:00.08| 77 | 19 | | 55 | VIEW | | 1 | 11 |00:00:00.08| 77 | 19 | |* 56 | MAT_VIEW ACCESS BY INDEX ROWID | TD_ROW_LEVEL_SECURITY_MV | 1 | 11 |00:00:00.05| 67 | 16 | | 57 | NESTED LOOPS | | 1 | 2015 |00:00:00.03| 43 | 6 | | 58 | MERGE JOIN CARTESIAN | | 1 | 11 |00:00:00.01| 16 | 0 | | 59 | MAT_VIEW ACCESS BY INDEX ROWID | TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01| 3 | 0 | |* 60 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01| 2 | 0 | | 61 | BUFFER SORT | | 1 | 11 |00:00:00.01| 13 | 0 | |* 62 | MAT_VIEW ACCESS BY INDEX ROWID| TD_CLUP_DETAIL_MV | 1 | 11 |00:00:00.01| 13 | 0 | |* 63 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N2 | 1 | 11 |00:00:00.01| 2 | 0 | |* 64 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N2 | 11 | 2003 |00:00:00.03| 27 | 6 | |* 65 | INDEX RANGE SCAN | TW_DIM_CLUP_N5 | 11 | 11 |00:00:00.01| 13 | 0 | | 66 | VIEW | | 1 | 99592 |00:00:51.47| 45838 | 45809 | | 67 | HASH GROUP BY | | 1 | 99592 |00:00:51.47| 45838 | 45809 | | 68 | TABLE ACCESS BY INDEX ROWID | TW_FACT_CLUP_MONTHLY | 1 | 99592 |00:00:51.02| 45838 | 45725 | | 69 | NESTED LOOPS | | 1 | 99594 |00:00:00.50| 116 | 113 | | 70 | VIEW | | 1 | 1 |00:00:00.01| 3 | 0 | | 71 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D35_64822175 | 1 | 1 |00:00:00.01| 3 | 0 | |* 72 | INDEX RANGE SCAN | TW_FACT_CLUP_EOM_TIME_SYS_N1| 1 | 99592 |00:00:00.27| 113 | 113 | | 73 | VIEW | | 1 | 111K|00:01:31.06| 101K| 101K| | 74 | HASH GROUP BY | | 1 | 111K|00:01:31.06| 101K| 101K| | 75 | TABLE ACCESS BY INDEX ROWID | TW_FACT_CLUP_MONTHLY | 1 | 331K|00:01:29.92| 101K| 101K| | 76 | NESTED LOOPS | | 1 | 331K|00:00:01.32| 576 | 373 | | 77 | NESTED LOOPS | | 1 | 91 |00:00:00.01| 26 | 2 | | 78 | VIEW | | 1 | 1 |00:00:00.01| 3 | 2 | | 79 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D34_64822175 | 1 | 1 |00:00:00.01| 3 | 2 | |* 80 | TABLE ACCESS FULL | TW_DIM_TIME | 1 | 91 |00:00:00.01| 23 | 0 | |* 81 | INDEX RANGE SCAN | TW_FACT_CLUP_EOM_TIME_SYS_N1| 91 | 331K|00:00:00.81| 550 | 371 | | 82 | VIEW | | 1 | 112K|00:01:38.77| 109K| 108K| | 83 | HASH GROUP BY | | 1 | 112K|00:01:38.77| 109K| 108K| | 84 | TABLE ACCESS BY INDEX ROWID | TW_FACT_CLUP_MONTHLY | 1 | 335K|00:01:37.63| 109K| 108K| | 85 | NESTED LOOPS | | 1 | 335K|00:00:01.33| 588 | 375 | | 86 | NESTED LOOPS | | 1 | 95 |00:00:00.01| 26 | 2 | | 87 | VIEW | | 1 | 1 |00:00:00.01| 3 | 2 | | 88 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D32_64822175 | 1 | 1 |00:00:00.01| 3 | 2 | |* 89 | TABLE ACCESS FULL | TW_DIM_TIME | 1 | 95 |00:00:00.01| 23 | 0 | |* 90 | INDEX RANGE SCAN | TW_FACT_CLUP_EOM_TIME_SYS_N1| 95 | 335K|00:00:00.81| 562 | 373 | | 91 | VIEW | | 1 | 112K|00:00:17.72| 35623 | 35411 | | 92 | HASH GROUP BY | | 1 | 112K|00:00:17.61| 35623 | 35411 | | 93 | TABLE ACCESS BY INDEX ROWID | TW_FACT_CLUP_MONTHLY | 1 | 112K|00:00:17.30| 35623 | 35411 | | 94 | NESTED LOOPS | | 1 | 112K|00:00:00.34| 130 | 128 | | 95 | VIEW | | 1 | 1 |00:00:00.01| 3 | 2 | | 96 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D35_64822175 | 1 | 1 |00:00:00.01| 3 | 2 | |* 97 | INDEX RANGE SCAN | TW_FACT_CLUP_EOM_TIME_SYS_N1| 1 | 112K|00:00:00.16| 127 | 126 | ---------------------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):! ! ! ! 11!
  • 34. ! ! ! --------------------------------------------------- 1 - filter(ROWNUM=1) 2 - filter(UPPER("CON"."POSITION_TYPE_CD")=PRINCIPAL) 3 - access("CON"."LOC_SYS_ID"=:B1) 9 - filter(("ACCT_MONTH_YEAR"<=200912 AND "ACTUAL_DATE"<SYSDATE@!)) 10 - access("IS_ACCT_END_OF_MONTH"=1) 12 - access("T3"."TIME_WH_SYS_ID"="T"."TIME_WH_SYS_ID") 23 - filter("T2"."ACCT_PERIOD_DT"=ADD_MONTHS(INTERNAL_FUNCTION("CURR_PERIOD"."ACCT_PERIOD_DT"),-12)) 43 - access("IS_ACCT_END_OF_MONTH"=1) 45 - access("CLUP"."CLUP_WH_SYS_ID"="CURR_YTD_NET_PRM"."CLUP_WH_SYS_ID") 46 - access("CLUP"."CLUP_WH_SYS_ID"="CURR_Q_NET_PRM"."CLUP_WH_SYS_ID") 47 - access("CLUP"."CLUP_WH_SYS_ID"="PRIOR_Q_NET_PRM"."CLUP_WH_SYS_ID") 48 - access("CLUP"."CLUP_WH_SYS_ID"="PRIOR_YTD_NET_PRM"."CLUP_WH_SYS_ID") 56 - filter("RL"."USER_SYS_ID"="I"."INDIV_SYS_ID") 60 - access("I"."USER_LOGIN_ID"=TraxReporting) 62 - filter(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) 63 - access("CD"."CUST_SYS_ID"=5922) 64 - access("CD"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 65 - access("LOC_DETAILS"."CLUP_SYS_ID"="CLUP"."CLUP_SYS_ID") 72 - access("FCM"."TIME_WH_SYS_ID"="TS"."PRIOR_YR_TIME_SYS_ID") 80 - filter(("T5"."ACCT_MONTH_YEAR">="PQ"."BEGIN_PRIOR_QTR" AND "T5"."ACCT_MONTH_YEAR"<="PQ"."END_PRIOR_QTR")) 81 - access("FCM"."TIME_WH_SYS_ID"="T5"."TIME_WH_SYS_ID") 89 - filter(("T6"."ACCT_MONTH_YEAR">="CQ"."BEGIN_CURR_QTR" AND "T6"."ACCT_MONTH_YEAR"<="CQ"."END_CURR_QTR")) 90 - access("FCM"."TIME_WH_SYS_ID"="T6"."TIME_WH_SYS_ID") 97 - access("FCM"."TIME_WH_SYS_ID"="TS"."TIME_WH_SYS_ID") :>%!&/G7(6/!%)%)!75!?7((6;!(>%!G%;(>!/B!(>%!/$6;6-G!&(-(%4%(!*+!4/$%!(>-!>-GBL!g6$(7-GG+!-GG!(>%!A/$J!(/!B6;7$%!/7(!(64%!5%$6/)&!-)!?/457(%!V-G7%&!B/$!%-?>!5%$6/)!6)6V6)7-GG+!A-&!$%5G-?%)!*+!&645G+!;$/756;!*+!(>%!+%-$!-)!X7-$(%$!_)%(%$46%)!*+!7&6;!(/j?>-$_v)-(%!B6%G)wKUOU``!-)!7&6;!(>%!SFPPT#!/5(6/!/B!dSFT#!YZ!(/!;%(!47G(65G%!G%V%G&!/B!(/(-G&L!WITH /* k2rewrite */access_lvl as(SELECT row_access_auth_cd, indiv_sys_id FROM td_individual_mv WHERE user_login_id = TraxReporting),clups AS(SELECT cd.clup_sys_idFROM td_clup_detail_mv cd, access_lvl aWHERE cd.doc_type_cd IN (AGENCY, FNAS-LNR)AND cd.cust_sys_id = 5922AND a.row_access_auth_cd = RESTRICTEDAND cd.clup_sys_id in (select rl.clup_sys_id from td_row_level_security_mv rl where rl.user_sys_id = a.indiv_sys_id)UNION ALLSELECT cd.clup_sys_idFROM td_clup_detail_mv cd, access_lvl aWHERE cd.doc_type_cd IN (AGENCY, FNAS-LNR)AND cd.cust_sys_id = 5922AND a.row_access_auth_cd = UNRESTRICTED),ans as(SELECT dtl.clup_sys_id, dt.acct_year, to_char(dt.acct_period_dt,Q) acct_qtr, SUM(NVL (fcm.net_prm_tot_eom_amt, 0)) net_prmFROM clups dtl ,tw_dim_clup clup ,tw_fact_clup_monthly fcm ,tw_dim_time dtWHERE dtl.clup_sys_id = clup.clup_sys_idAND clup.clup_wh_sys_id = fcm.clup_wh_sys_idAND fcm.time_wh_sys_id = dt.time_wh_sys_idAND dt.acct_month_year BETWEEN 200801 AND 200912AND dt.is_acct_end_of_month = 1GROUP BY dtl.clup_sys_id, ROLLUP ( dt.acct_year, to_char(dt.acct_period_dt,Q) )),dtls as(select cd.rollup_uw_abbv_cd!! 1! ! ! ! ! ! ! ! ! ! !
  • 35. ! ! ! ! !! ! ,CASE WHEN cd.cust_loc_nm IS NOT NULL AND cd.dba_nm_from_loc_nm_ind = 1 THEN cd.cust_loc_nm WHEN cd.cust_doing_bus_as_nm IS NOT NULL THEN cd.cust_doing_bus_as_nm ELSE cd.cust_bus_nm END cust_loc_nm ,cd.loc_city_nm , cd.loc_rep_f_nm || || cd.loc_rep_mid_int_nm || || cd.loc_rep_l_nm AS loc_rep_nm , (SELECT NVL (con.first_nm, ) || || NVL (con.mid_int_nm, ) || || NVL (con.last_nm, ) || || NVL (con.sufx_nm, ) FROM td_contact_mv con WHERE con.loc_sys_id = cd.loc_sys_id AND UPPER (con.position_type_cd) = PRINCIPAL AND ROWNUM = 1) principal_nm, ans.acct_year, ans.acct_qtr, ans.net_prmfrom ans, td_clup_detail_mv cdwhere ans.clup_sys_id = cd.clup_sys_id),outlist1 as(select rollup_uw_abbv_cd ,cust_loc_nm ,loc_city_nm ,loc_rep_nm ,principal_nm ,acct_year ,acct_qtr ,sum(net_prm) as net_prmfrom dtlsgroup by rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm,acct_year,acct_qtr),outlist2 as(select rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm, curr_yr_ytd, prior_yr_ytd, curr_yr_ytd - prior_yr_ytd as ytd_variancefrom(select rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm, max( decode( acct_year, 2009, net_prm, null ) ) curr_yr_ytd, max( decode( acct_year, 2008, net_prm, null ) ) prior_yr_ytdfrom outlist1where (acct_year between 2008 and 2009and acct_qtr is null)group by rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm)),outlist3 as(select rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm, curr_qtr_ytd - prior_qtr_ytd as qvariancefrom(select rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm, max( decode( acct_qtr, 4, net_prm, null ) ) curr_qtr_ytd, max( decode( acct_qtr, 3, net_prm, null ) ) prior_qtr_ytdfrom outlist1where (acct_year = 2009and acct_qtr between 3 and 4)group by rollup_uw_abbv_cd, cust_loc_nm, loc_city_nm, loc_rep_nm, principal_nm, acct_year))select a.rollup_uw_abbv_cd, a.cust_loc_nm, a.loc_city_nm, a.loc_rep_nm, a.principal_nm, a.curr_yr_ytd, a.prior_yr_ytd, a.ytd_variance, b.qvariancefrom outlist2 a, outlist3 bwhere a.rollup_uw_abbv_cd = b.rollup_uw_abbv_cdand a.cust_loc_nm = b.cust_loc_nmand a.loc_city_nm = b.loc_city_nmand a.loc_rep_nm = b.loc_rep_nmand a.principal_nm = b.principal_nmorder by a.cust_loc_nm, a.loc_city_nm, a.loc_rep_nm, a.principal_nm, a.rollup_uw_abbv_cd;! ! ! ! 1a!
  • 36. ! ! ! :>%!&(-(%4%(K!A>6G%!&(6GG!G%;(>+K!A-&!47?>!&>/$(%$!-)!G%&&!?74*%$&/4%!(>-!(>%!/$6;6-GL!W(!-G&/!$%4/V%)!$%5%-(%)!-??%&&%&!(/!/*]%?(&!_(-J6;!?-$%!/B!/7$!Nd-(G6;!;7Q!-(65-((%$!%G646-(6/`!$%&7G(6;!6!-!47?>!4/$%!&($%-4G6%)!-)!%BB6?6%(!&(-(%4%(!-&!%V6)%?%)!*+!(>%!%A!%@%?7(6/!5G-H!SQL_ID b7tqyy6htag53, child number 0-------------------------------------Plan hash value: 1922825908--------------------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name |Starts |A-Rows | A-Time |Buffers | Reads |--------------------------------------------------------------------------------------------------------------------------------------| 1 | TEMP TABLE TRANSFORMATION | | 1 | 8 |00:00:07.52 | 1853 | 1348 || 2 | LOAD AS SELECT | | 1 | 1 |00:00:00.01 | 7 | 0 || 3 | MAT_VIEW ACCESS BY INDEX ROWID | TD_INDIVIDUAL_MV | 1 | 1 |00:00:00.01 | 3 | 0 ||* 4 | INDEX RANGE SCAN | TD_INDIVIDUAL_N1 | 1 | 1 |00:00:00.01 | 2 | 0 || 5 | LOAD AS SELECT | | 1 | 1 |00:00:07.51 | 1831 | 1347 || 6 | HASH GROUP BY | | 1 | 86 |00:00:07.51 | 1827 | 1347 || 7 | VIEW | | 1 | 119 |00:00:07.51 | 1827 | 1347 || 8 | MAT_VIEW ACCESS BY INDEX ROWID | TD_CLUP_DETAIL_MV | 1 | 119 |00:00:07.50 | 1818 | 1344 || 9 | NESTED LOOPS | | 1 | 239 |00:00:07.50 | 1807 | 1344 || 10 | VIEW | | 1 | 119 |00:00:07.48 | 1686 | 1342 || 11 | SORT GROUP BY ROLLUP | | 1 | 119 |00:00:07.48 | 1686 | 1342 ||* 12 | HASH JOIN | | 1 | 258 |00:00:07.48 | 1686 | 1342 || 13 | TABLE ACCESS BY INDEX ROWID | TW_FACT_CLUP_MONTHLY | 1 | 1607 |00:00:07.47 | 1666 | 1342 || 14 | NESTED LOOPS | | 1 | 1619 |00:00:00.04 | 75 | 11 || 15 | NESTED LOOPS | | 1 | 11 |00:00:00.01 | 46 | 4 || 16 | VIEW | | 1 | 11 |00:00:00.01 | 22 | 1 || 17 | UNION-ALL | | 1 | 11 |00:00:00.01 | 22 | 1 || 18 | NESTED LOOPS SEMI | | 1 | 0 |00:00:00.01 | 6 | 1 || 19 | MERGE JOIN CARTESIAN | | 1 | 0 |00:00:00.01 | 6 | 1 ||* 20 | VIEW | | 1 | 0 |00:00:00.01 | 6 | 1 || 21 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D36_64822175 | 1 | 1 |00:00:00.01 | 6 | 1 || 22 | BUFFER SORT | | 0 | 0 |00:00:00.01 | 0 | 0 ||* 23 | MAT_VIEW ACCESS BY INDEX ROWID| TD_CLUP_DETAIL_MV | 0 | 0 |00:00:00.01 | 0 | 0 ||* 24 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N2 | 0 | 0 |00:00:00.01 | 0 | 0 ||* 25 | MAT_VIEW ACCESS BY INDEX ROWID | TD_ROW_LEVEL_SECURITY_MV | 0 | 0 |00:00:00.01 | 0 | 0 ||* 26 | INDEX RANGE SCAN | TD_ROW_LEVEL_SECURITY_MV_N2 | 0 | 0 |00:00:00.01 | 0 | 0 || 27 | MERGE JOIN CARTESIAN | | 1 | 11 |00:00:00.01 | 16 | 0 ||* 28 | VIEW | | 1 | 1 |00:00:00.01 | 3 | 0 || 29 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D36_64822175 | 1 | 1 |00:00:00.01 | 3 | 0 || 30 | BUFFER SORT | | 1 | 11 |00:00:00.01 | 13 | 0 ||* 31 | MAT_VIEW ACCESS BY INDEX ROWID | TD_CLUP_DETAIL_MV | 1 | 11 |00:00:00.01 | 13 | 0 ||* 32 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N2 | 1 | 11 |00:00:00.01 | 2 | 0 || 33 | TABLE ACCESS BY INDEX ROWID | TW_DIM_CLUP | 11 | 11 |00:00:00.01 | 24 | 3 ||* 34 | INDEX RANGE SCAN | TW_DIM_CLUP_N5 | 11 | 11 |00:00:00.01 | 13 | 0 ||* 35 | INDEX RANGE SCAN | TW_FACT_CLUP_EOM_PK1 | 11 | 1607 |00:00:00.03 | 29 | 7 ||* 36 | TABLE ACCESS BY INDEX ROWID | TW_DIM_TIME | 1 | 24 |00:00:00.01 | 20 | 0 ||* 37 | INDEX RANGE SCAN | TW_DIM_TIME_N2 | 1 | 240 |00:00:00.01 | 3 | 0 ||* 38 | INDEX RANGE SCAN | TD_CLUP_DETAIL_MV_N6 | 119 | 119 |00:00:00.02 | 121 | 2 || 39 | SORT ORDER BY | | 1 | 8 |00:00:00.01 | 9 | 1 ||* 40 | HASH JOIN | | 1 | 8 |00:00:00.01 | 9 | 1 || 41 | VIEW | | 1 | 8 |00:00:00.01 | 6 | 1 || 42 | HASH GROUP BY | | 1 | 8 |00:00:00.01 | 6 | 1 ||* 43 | VIEW | | 1 | 16 |00:00:00.01 | 6 | 1 || 44 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D37_64822175 | 1 | 86 |00:00:00.01 | 6 | 1 || 45 | VIEW | | 1 | 8 |00:00:00.01 | 3 | 0 || 46 | HASH GROUP BY | | 1 | 8 |00:00:00.01 | 3 | 0 ||* 47 | VIEW | | 1 | 16 |00:00:00.01 | 3 | 0 || 48 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6D37_64822175 | 1 | 86 |00:00:00.01 | 3 | 0 |--------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 4 - access("USER_LOGIN_ID"=TraxReporting) 12 - access("FCM"."TIME_WH_SYS_ID"="DT"."TIME_WH_SYS_ID") 20 - filter("A"."ROW_ACCESS_AUTH_CD"=RESTRICTED) 23 - filter(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) 24 - access("CD"."CUST_SYS_ID"=5922) 25 - filter("RL"."USER_SYS_ID"="A"."INDIV_SYS_ID") 26 - access("CD"."CLUP_SYS_ID"="RL"."CLUP_SYS_ID") 28 - filter("A"."ROW_ACCESS_AUTH_CD"=UNRESTRICTED) 31 - filter(("CD"."DOC_TYPE_CD"=AGENCY OR "CD"."DOC_TYPE_CD"=FNAS-LNR)) 32 - access("CD"."CUST_SYS_ID"=5922)!! 1D! ! ! ! ! ! ! ! ! ! !
  • 37. ! ! ! ! !! ! 34 - access("DTL"."CLUP_SYS_ID"="CLUP"."CLUP_SYS_ID") 35 - access("CLUP"."CLUP_WH_SYS_ID"="FCM"."CLUP_WH_SYS_ID") 36 - filter(("DT"."ACCT_MONTH_YEAR">=200801 AND "DT"."ACCT_MONTH_YEAR"<=200912)) 37 - access("DT"."IS_ACCT_END_OF_MONTH"=1) 38 - access("ANS"."CLUP_SYS_ID"="CD"."CLUP_SYS_ID") 40 - access("A"."ROLLUP_UW_ABBV_CD"="B"."ROLLUP_UW_ABBV_CD" AND "A"."CUST_LOC_NM"="B"."CUST_LOC_NM" AND "A"."LOC_CITY_NM"="B"."LOC_CITY_NM" AND "A"."LOC_REP_NM"="B"."LOC_REP_NM" AND "A"."PRINCIPAL_NM"="B"."PRINCIPAL_NM") 43 - filter(("ACCT_YEAR">=2008 AND "ACCT_YEAR"<=2009 AND "ACCT_QTR" IS NULL)) 47 - filter(("ACCT_YEAR"=2009 AND "ACCT_QTR">=3 AND "ACCT_QTR"<=4)) i/(!/G+!)6)!(>%!%@%?7(6/!(64%!?/4%!)/A!(/!7)%$!e!&%?/)&K!A%GG!7)%$!(>%!/G6%!(64%/7(K!*7(!(>%!*G/?J!-??%&&%&!)$/55%)!B$/4!%-$G+!188,!)/A!(/!]7&(!"Kea1L!:>%!*/((/4^G6%!A6(>!(>6&!-(65-((%$!6&!(>-(!6B!+/7!(>6J!&/4%(>6;!6&!]7&(!(//!?/45G%@!-)!G%;(>+K!6(!5$/*-*G+!6&L!XBX a632&-.NN.K%#$&5,.0+D6,+M&:>%!N]7&(!B/GG/A6;!5$/?%)7$%Q!-(65-((%$!/??7$&!A>%!)%V%G/5%$&!>-V%!)6BB6?7G(+!4-J6;!(>%!G%-5!B$/4!-!5$/?%)7$-G!A-+!/B!(>6J6;!(/!-!&%(^*-&%)!A-+!/B!(>6J6;L!WB!+/7!(>6J!5$/?%)7$-GG+K!+/7U$%!(>6J6;!6!(%$4&!/B!/%!$/A!-(!-!(64%L!Z/7UGG!/B(%!B6)!+/7$&%GB!5/)%$6;!>/A!(/!>-)G%!+/7$!X7%$+!B/$47G-(6/!A6(>!5>$-&%&!G6J%!NB/$!%-?>!$/A!)/!@Q!/$!NA>6G%!V-G7%!6&!+!)/![LQ!<%V%G/56;!3OP!7&6;!(>6&!A-+!/B!(>6J6;!?-!/B(%!)$6V%!?>/6?%&!(>-(!4-+!/(!5%$B/$4!-&!A%GG!-&!-!-G(%$-(%!-55$/-?>!?$%-(%)!7&6;!-!&%(^*-&%)!A-+!/B!(>6J6;L!XBXB9 FQ"/5N+]&A./562+&"#&"I+,"$+&#6/P+,&.-&D"43&P+2K++#&.,D+,3&-.,&"&0632./+,& W!(>6&!%@-45G%K!(>%!(-&J!6&!(/!?/457(%!-!-V%$-;%!74*%$!/B!)-+&!*%(A%%!/$)%$&!B/$!-!?7&(/4%$!_/$!G6&(!/B!?7&(/4%$&`L!I!5$/?%)7$-G!-55$/-?>!(/!A$6(6;!(>6&!&(-(%4%(!4-+!6V/GV%!%@%?7(6;!&%V%$-G!)6BB%$%(!X7%$6%&!(/!>%G5!*76G)!(>%!)-(-!%%)%)!/%!&(%5!-(!-!(64%L!! SQL> -- Show the list of order dates for customer 102 SQL> select customer_id, order_date 2 from orders 3 where customer_id = 102 ; CUSTOMER_ID ORDER_DATE --------------- ------------------------------- 102 19-NOV-07 03.41.54.696211 PM 102 14-SEP-07 08.53.40.223345 AM 102 29-MAR-07 01.22.40.536996 PM 102 14-SEP-06 06.03.04.763452 AM SQL> SQL> -- Determine the order_date prior to the current rows order_date SQL> select customer_id, order_date, 2 lag(order_date,1,order_date) 3 over (partition by customer_id order by order_date) 4 as prev_order_date 5 from orders 6 where customer_id = 102; CUSTOMER_ID ORDER_DATE PREV_ORDER_DATE --------------- ----------------------------- ----------------------------- 102 14-SEP-06 06.03.04.763452 AM 14-SEP-06 06.03.04.763452 AM 102 29-MAR-07 01.22.40.536996 PM 14-SEP-06 06.03.04.763452 AM 102 14-SEP-07 08.53.40.223345 AM 29-MAR-07 01.22.40.536996 PM 102 19-NOV-07 03.41.54.696211 PM 14-SEP-07 08.53.40.223345 AM SQL> SQL> -- Determine the days between each order SQL> select trunc(order_date) - trunc(prev_order_date) days_between 2 from 3 ( 4 select customer_id, order_date, 5 lag(order_date,1,order_date) 6 over (partition by customer_id order by order_date) 7 as prev_order_date 8 from orders 9 where customer_id = 102!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 !C>-5(%$!!9!3OP!W&!I*/7(!3%(&!6!G#(/H#".-$/IJK!xI5$%&&!08"8K!,-$%!!./$(/K!%(L!-GLy!>-&!4/$%!)%(-6GL!! ! ! ! 1c!
  • 38. ! ! ! 10 ); DAYS_BETWEEN --------------- 0 196 169 66 SQL> SQL> -- Put it together with an AVG function to get the final answer SQL> select avg(trunc(order_date) - trunc(prev_order_date)) avg_days_between 2 from 3 ( 4 select customer_id, order_date, 5 lag(order_date,1,order_date) 6 over (partition by customer_id order by order_date) 7 as prev_order_date 8 from orders 9 where customer_id = 102 10 ); AVG_DAYS_BETWEEN ---------------- 107.75 ! :>6&!G//J&!5$%((+!%G%;-(K!)/%&U(!6(R!W!(>6&!%@-45G%K!WUV%!%@%?7(%)!&%V%$-G!X7%$6%&!/%^*+^/%!(/!&>/A!+/7!>/A!4+!(>6J6;!B/GG/A%)!-!&(%5^*+^&(%5!5$/?%)7$-G!-55$/-?>!(/!A$6(6;!(>%!X7%$+L!M>-(!WUV%!)/%!6&!(/!$%-)!%-?>!/$)%$!$/A!B/$!?7&(/4%$!"80!6!/$)%$!*+!/$)%$j)-(%!-)K!7&6;!-!PId!B7?(6/K!G//J!*-?J!-(!(>%!5$6/$!/$)%$!$/A!(/!;%(!6(&!/$)%$j)-(%L!F?%!W!>-V%!*/(>!)-(%&K!(>%!)-(%!B/$!(>%!?7$$%(!$/AU&!/$)%$!-)!(>%!)-(%!B/$!(>%!5$%V6/7&!$/AU&!/$)%$K!6(U&!-!&645G%!4-((%$!(/!&7*($-?(!(>%!(A/!(/!;%(!(>%!)-+&!*%(A%%L!P-&(G+K!W!7&%!(>%!-V%$-;%!-;;$%;-(%!B7?(6/!(/!;%(!4+!B6-G!-&A%$L! Z/7!?-!(%GG!(>-(!(>6&!X7%$+!6&!*76G(!B/GG/A6;!-!V%$+!5$/?%)7$-G!-55$/-?>L!:>%!*%&(!;6V%-A-+!(/!J/A6;!(>%!-55$/-?>!6&!(>%!A-+!W!?-!A-GJ!(>$/7;>!&%V%$-G!)6BB%$%(!X7%$6%&!(/!&>/A!>/A!(>%!B6-G!$%&7G(!&%(!A-&!*76G(L!W!?/7G)!&%%!(>%!)%(-6G&!-&!W!A%(!-G/;L!M>%!+/7U$%!(>6J6;!6!&%(&K!+/7UGG!B6)!(>-(!+/7!)/U(!$%-GG+!?-$%!-*/7(!%-?>!6)6V6)7-G!%G%4%(L!! W!?/7G)!>-V%!)%$6V%)!(>%!&-4%!-&A%$!7&6;!-!&%(^*-&%)!(>6J6;!-55$/-?>!(/!?$%-(%!(>%!B/GG/A6;!X7%$+H! SQL> select (max(trunc(order_date)) - min(trunc(order_date))) / count(*) as avg_days_between 2 from orders 3 where customer_id = 102 ; AVG_DAYS_BETWEEN ---------------- 107.75 36?%!(>6&!%@-45G%!7&%&!-!V%$+!&4-GG!(-*G%!_6(!/G+!>-&!"8a!$/A&`K!(>%$%!-$%!/!)6&?%$-*G%!5%$B/$4-?%!645-?(L!2/A%V%$K!6B!+/7!(-J%!(>6&!&-4%!%@-45G%!-)!($-&G-(%!6(!(/!-!G-$;%$!)-(-&%(K!+/7!?-!*%;6!(/!&%%!&/4%!)6BB%$%?%&!-&!&>/A!6!(>6&!?/45-$6&/H!SQL> select /* kmset */ (max(trunc(acct_period_month_yr_dt)) - min(trunc(acct_period_month_yr_dt))) / count(*) as avg_days_between 2 from tr_policy_h 3 where cust_sys_id = 1039 ;AVG_DAYS_BETWEEN---------------- 1.7340471092077SQL> @pln kmsetSQL_ID 24pcka78mrtdr, child number 0-------------------------------------!! 1e! ! ! ! ! ! ! ! ! ! !
  • 39. ! ! ! ! !! !Plan hash value: 1921842268-----------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |-----------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 18 ||* 2 | INDEX RANGE SCAN| TR_POLICY_H_N14 | 1 | 4013 | 2335 |00:00:00.01 | 18 |-----------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("CUST_SYS_ID"=1039)SQL> select /* kmproc */ avg(trunc(acct_period_month_yr_dt) - trunc(prev_prd_date)) avg_days_between 2 from 3 ( 4 select cust_sys_id, acct_period_month_yr_dt, 5 lag(acct_period_month_yr_dt,1,acct_period_month_yr_dt) 6 over (partition by cust_sys_id order by acct_period_month_yr_dt) 7 as prev_prd_date 8 from tr_policy_h 9 where cust_sys_id = 1039 10 );AVG_DAYS_BETWEEN---------------- 1.7340471092077SQL> @pln kmprocSQL_ID af532p311fdz9, child number 0-------------------------------------Plan hash value: 3344845210------------------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts |A-Rows | A-Time |Buffers |Reads | OMem | 1Mem | Used-Mem |------------------------------------------------------------------------------------------------------------------------------------| 1 | SORT AGGREGATE | | 1 | 1 |00:00:06.39 | 979 | 634 | | | || 2 | VIEW | | 1 | 2335 |00:00:06.38 | 979 | 634 | | | || 3 | WINDOW SORT | | 1 | 2335 |00:00:06.38 | 979 | 634 | 124K| 124K| 110K (0)|| 4 | TABLE ACCESS BY INDEX ROWID| TR_POLICY_H | 1 | 2335 |00:00:06.37 | 979 | 634 | | | ||* 5 | INDEX RANGE SCAN | TR_POLICY_H_N14 | 1 | 2335 |00:00:00.01 | 18 | 0 | | | |------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 5 - access("CUST_SYS_ID"=1039) I&!+/7!?-!&%%K!(>%!G-$;%$!V/G74%!/B!)-(-!&(-$(&!(/!$%V%-G!)6BB%$%?%&!6!>/A!(>%!(A/!X7%$6%&!5%$B/$4L!W!)/U(!(>6J!(>%!5$/?%)7$-G!-55$/-?>!6&!?/45G%(%G+!N*-)QL!Y7(!W!)/!(>6J!;%((6;!%($%?>%)!6!)%V%G/56;!X7%$6%&!7&6;!(>6&!4%(>/)!?-!G%-)!(/!B/$47G-(6;!X7%$6%&!(>-(!5%$B/$4!G%&&!%BB6?6%(G+!(>-!(>/&%!+/7!B/$47G-(%!7&6;!-!&%(^*-&%)!-55$/-?>L!:>%!&/G7(6/!(/!-V/6)6;!(>%!N]7&(!B/GG/A6;!5$/?%)7$%Q!-(65-((%$!6&!(/!&>6B(!+/7$!(>6J6;!(/!&(-$(!*+!&%-$?>6;!B/$!-!&%(^*-&%)!-55$/-?>!-)!4/V%!(/A-$)&!-!4/$%!5$/?%)7$-G!-55$/-?>!/G+!A>%!-)!(/!(>%!)%;$%%!%%)%)L!XB[ <&K"#2&%2&"NN&W!/B(%!(>6J!/B!(>6&!-&!*%6;!(>%!G-[+!4-U&!-(65-((%$!&6?%!6(!(-J%&!4/$%!%BB/$(!(/!(+5%!6!(>%!&5%?6B6?!?/G74&!+/7!%%)!V%$&7&!7&6;!(>%!?-(?>^-GG!-55$/-?>L!W!?-GG!6(!NW!A-(!6(!-GGQ!*%?-7&%!3OP!6&!/B(%!A$6((%!A6(>!(>%!7)%$G+6;!6)%-!(>-(!A>6G%!W!46;>(!/(!%%)!(>-(!)-(-!/AK!W!4-+!%%)!6(!G-(%$K!&/!WUGG!]7&(!&-V%!4+&%GB!&/4%!(64%!-)!4-J%!%V%$+(>6;!-V-6G-*G%!/AL!k$%X7%(!/??7$$%?%!/B!N3EPEC:!pQ!X7%$6%&K!V6%A&!(>-(!%@($-?(!-GG!?/G74&K!/$!T#<I:E!&(-(%4%(&!(>-(!75)-(%!%V%$+!?/G74K!$%;-$)G%&&!/B!A>%(>%$!(>%+!%%)!(/!*%!75)-(%)!/$!/(K!%@>6*6(!(>6&!-(65-((%$L!! ! ! ! 1m!
  • 40. ! ! !XB[B9 FQ"/5N+]&F)FA:&b&I3B&F)FA:&c0.N6/#&N%32d&M>%!X7%$+6;!-!(-*G%!_5-$(6?7G-$G+!-!G-$;%!(-*G%`!(>-(!%%)&!(/!*%!&/$(%)!/$!%V%!]/6%)!(/!-/(>%$!(-*G%!7&6;!-!2I32!bFWi!/5%$-(6/K!&5%?6B+6;!-!?/G74!G6&(!A6GG!$%)7?%!(>%!-4/7(!/B!4%4/$+!%%)%)!(/!5$/?%&&!(>%!&/$(=>-&>!V%$&7&!&5%?6B+6;!-GG!?/G74&!*%!$%(7$%)L!W(U&!%-&+!(/!&%%!(>%!)6BB%$%?%!A6(>!-!&645G%!?/45-$6&/!(%&(!7&6;!(>%&%!(A/!X7%$6%&H! select /* km_all */ * from my_objects order by owner, object_name select /* km_only */ owner, object_name from my_objects order by owner, object_name i/(6?%!(>-(!A>6G%!*/(>!X7%$6%&!A6GG!%@%?7(%!-!B7GG!(-*G%!&?-K!-)!(>7&!-??%&&!(>%!&-4%!*G/?J&K!(>%!X7%$+!(>-(!&5%?6B6%&!/G+!(A/!?/G74&!(/!*%!$%(7$%)!7&%&!G%&&!4%4/$+!(/!>-)G%!(>%!&/$(L!:>6&!)6BB%$%?%!$%)7?%&!(>%!$%&5/&%!(64%!*+!-!G6((G%!4/$%!-!&%?/)L! SQL_ID 8qf110gcy0zf6, child number 0 ------------------------------------- select /* km_all */ * from my_objects order by owner, object_name Plan hash value: 3173709044 ------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 434K|00:00:04.41 | 5986 | 5983 | | | | | 1 | SORT ORDER BY | | 1 | 434K| 434K|00:00:04.41 | 5986 | 5983 | 57M| 2653K| 51M (0)| | 2 | TABLE ACCESS FULL| MY_OBJECTS | 1 | 434K| 434K|00:00:02.61 | 5986 | 5983 | | | | ------------------------------------------------------------------------------------------------------------------------------- SQL_ID 09rv44ga24u2u, child number 0 ------------------------------------- select /* km_only */ owner, object_name from my_objects order by owner, object_name Plan hash value: 3173709044 ------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 434K|00:00:03.38 | 5986 | 5978 | | | | | 1 | SORT ORDER BY | | 1 | 434K| 434K|00:00:03.38 | 5986 | 5978 | 18M| 1608K| 16M (0)| | 2 | TABLE ACCESS FULL| MY_OBJECTS | 1 | 434K| 434K|00:00:01.94 | 5986 | 5978 | | | | ------------------------------------------------------------------------------------------------------------------------------- i/A!64-;6%!(>6&!%BB%?(!4-;6B6%)!-?$/&&!G-$;%$!)-(-&%(&L!S%&5/&%!(64%&!?/7G)!*%!6?$%-&%)!*+!&%?/)&!/$!467(%&!)%5%)6;!/!(>%!*+(%&!/B!)-(-!B$/4!?/G74&!(>-(!7G(64-(%G+!A/U(!*%!6?G7)%)!6!(>%!B6-G!$%&7G(!&%(L!M>+!A-&(%!(>%!(64%!-)!$%&/7$?%&!(/!/G+!(>$/A!-A-+!(>%!)-(-!G-(%$R!! :>6&!-(65-((%$!)/%&U(!]7&(!&>/A!75!6!(>%!7&%!/B!N3EPEC:!pQ!*7(!+/7UGG!B$%X7%(G+!&%%!6(!6!(>%!?$%-(6/!-)!7&%!/B!N/%!&6[%!B6(&!-GGQ!V6%A&L!I!V6%A!A6GG!*%!?$%-(%)!(>-(!?/(-6&!74%$/7&!?/G74&!(>-(!X7%$6%&!-;-6&(!(>%!V6%A!%V%$!$%X7%&(L!Y7(K!(>%!V6%A!?/(-6&!(>/&%!?/G74&!8@3)/,%/."3$!&/4%/%!46;>(!%V%$!%%)!(>%4L!W!-)V/?-(%!-;-6&(!(>6&!-55$/-?>!-)!6&(%-)!5$%B%$!(/!&%%!V6%A&!*%!4/)6B6%)!(/!-))!?/G74&!6B=A>%!%?%&&-$+!-)!/(!7(6G!(>-(!%%)!4-+!-$6&%L!XB[B7 FQ"/5N+]&@*;C:F&2H"2&3+2&Q&e&Q&:>%!/(>%$!?/44/!/??7$$%?%!/B!(>%!NW!A-(!6(!-GGQ!-(65-((%$!6&!B/7)!6!T#<I:E!&(-(%4%(&!A>%$%!V-G7%&!-$%!&%(!B/$!?/G74&!A>%!(>%!?/G74!V-G7%&!-$%U(!?>-;%)L!:>%!B/GG/A6;!&645G%!%@-45G%!)%4/&($-(%&!(>%!5%$B/$4-?%!5$/*G%4!(>6&!?-!?-7&%L!:>%!(%&(!(-*G%!>-&!/G+!1!?/G74&!_C"K!C0K!C1`!-)!/%!46GG6/!$/A&L!EV%$+!$/A!>-&!-!V-G7%!/B!"!B/$!C"!*7(!(>%$%!-$%!/G+!"88!$/A&!A>%$%!C0!z!"L!! SQL> @ds Table Owner : hr!! 8! ! ! ! ! ! ! ! ! ! !
  • 41. ! ! ! ! !! ! Table Name : redo_t Column List : c1,c2 Where Clause : Page Size[30]: Table blocks below hwm Table rows (B) (R) ---------------------- ---------------- 16,256 1,000,000 Block selectivity Block count Row selectivity Row count C1 C2 (pb = b/B) (b) (pr = r/R) (r) --------------- --------------- ----------------- -------------- ----------------- ---------------- 1 2 96.11% 15,624 99.99% 999,900 1 1 0.01% 2 0.01% 100 SQL> select n.name, t.value 2 from v$mystat t, v$statname n 3 where t.statistic# = n.statistic# 4 and n.name = redo size; NAME VALUE --------------- ---------- redo size 784 SQL> update /* upd1 */ redo_t 2 set c2 = 2 3 where c1 = 1; 1000000 rows updated. SQL> select n.name, t.value 2 from v$mystat t, v$statname n 3 where t.statistic# = n.statistic# 4 and n.name = redo size; NAME VALUE -------------- ---------- redo size 294319144 SQL> @pln upd1 SQL_ID 3vck7cgqa34us, child number 0 ------------------------------------- update /* upd1 */ redo_t set c2 = 2 where c1 = 1 Plan hash value: 2614511178 ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------------------ | 0 | UPDATE STATEMENT | | 3 | | | 4376 (100)| 0 |00:00:44.12 | 1444K| | 1 | UPDATE | REDO_T | 3 | | | | 0 |00:00:44.12 | 1444K| |* 2 | TABLE ACCESS FULL| REDO_T | 3 | 1000K| 5859K| 4376 (1)| 2009K|00:00:04.54 | 400K| ------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("C1"=1) SQL> select n.name, t.value 2 from v$mystat t, v$statname n 3 where t.statistic# = n.statistic# 4 and n.name = redo size; NAME VALUE --------------- ---------- redo size 784 SQL> update /* upd2 */ redo_t 2 set c2 = 2 3 where c1 = 1 4 and c2 != 2; 100 rows updated. SQL> select n.name, t.value! ! ! ! "!
  • 42. ! ! ! 2 from v$mystat t, v$statname n 3 where t.statistic# = n.statistic# 4 and n.name = redo size; NAME VALUE -------------- ---------- redo size 784 SQL> @pln upd2 SQL_ID fzw4mdkxr7565, child number 0 ------------------------------------- update /* upd2 */ redo_t set c2 = 2 where c1 = 1 and c2 != 2 Plan hash value: 2614511178 ------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------------------ | 0 | UPDATE STATEMENT | | 1 | | | 4377 (100)| 0 |00:00:00.11 | 15853 | | 1 | UPDATE | REDO_T | 1 | | | | 0 |00:00:00.11 | 15853 | |* 2 | TABLE ACCESS FULL| REDO_T | 1 | 500K| 2929K| 4377 (1)| 100 |00:00:00.11 | 15849 | ------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(("C2"<>2 AND "C1"=1))! :>%!4-6!5$/*G%4!>%$%!6&!6!(>%!;%%$-(6/!/B!%@?%&&!$%)/L!W!(>6&!&645G%!?-&%K!0m!.Y!/B!$%)/!A-&!;%%$-(%)L!:>%!(64%!(/!?/45G%(%!(>%!T#<I:E!A-&!?/&74%)!-G4/&(!%(6$%G+!*+!>-V6;!(/!>-)G%!(>%!$%)/L!Y7(!(>%!)-(-!/G+!>-)!"88!$/A&!(>-(!%%)%)!(/!*%!?>-;%)L!Y+!&645G+!-))6;!-!?>%?J!(/!-V/6)!75)-(6;!$/A&!A>%$%!(>%!?/G74!V-G7%!6&!-G$%-)+!&%(!(/!(>%!V-G7%!+/7!%%)K!+/7!-V/6)!75)-(6;!6B/$4-(6/!(>-(!)/%&U(!%%)!(/!*%L!:>6&!6&!-!?G-&&6?!5$//B!(/!)%(%$46%!(>%!B-&(%&(!A-+!(/!)/!&/4%(>6;!6&!(/!/(!)/!6(!-(!-GGL!XBf N.K&P4&3N.K&W!*/$$/A%)!:/4!,+(%U&!5>$-&%!(/!-4%!(>6&!-(65-((%$!-&!N&G/A!*+!&G/AQ!6&!(+56?-GG+!(>%!5%$B/$4-?%!B//(5$6(!B/$!3OP!(>-(!6&!?/)%)!7&6;!(>6&!-(65-((%$L!:>%$%!-$%!(A/!?-&%&!(>-(!WUGG!$%V6%A!(>-(!)%4/&($-(%!(>6&!-(65-((%$!-)!6(&!%BB%?(&L!XBfB9 FQ"/5N+]&;!)&%#3%D+&N..5&5,.0+33%#$&,.K3&.#+&"2&"&2%/+&&:>6&!6&!(>%!?G-&&6?!%@-45G%!/B!$/A^*+^$/A!5$/?%&&6;!-)!>-&!*%%!5$%-?>%)!%/7;>!(>-(!4/&(!5%/5G%!J/A!(/!-V/6)!6(K!*7(!6(!%V%$!>7$(&!(/!$%V6%A!6(!-;-6L!:>6&!-(65-((%$!&>/A&!75!A>%!(>%$%!6&!-!%%)!(/!)/!&/4%!6(%$4%)6-(%!5$/?%&&6;!/!$/A&!/B!)-(-!(>-(!6&!(//!?/45G%@!(/!*%!>-)G%)!*+!-!&6;G%!3OP!&(-(%4%(L!36?%!%-?>!$/A!6&!*%6;!$%V6%A%)!-)!?>-;%)!6)%5%)%(G+K!(>%!(%45(-(6/!6&!(/!?/45G%(%!A/$J!/!(>-(!$/A!*+!%@%?7(6;!(>%!$%X76$%)!75)-(%!644%)6-(%G+K!(>%!5$/?%%)!(/!(>%!%@(!$/AL!Y7(K!-&!(>6&!%@-45G%!&>/A&K!)/6;!&/!A6GG!-))!&6;6B6?-(!5%$B/$4-?%!/V%$>%-)L! SQL> alter session set tracefile_identifier = FOR_LOOP; Session altered. SQL> exec dbms_monitor.session_trace_enable; PL/SQL procedure successfully completed. SQL> SQL> DECLARE 2 TYPE NumTab IS TABLE OF widgets.widget_id%TYPE INDEX BY BINARY_INTEGER; 3 TYPE NameTab IS TABLE OF widgets.widget_nm%TYPE INDEX BY BINARY_INTEGER; 4 5 w_ids NumTab; 6 w_nms NameTab;!! 0! ! ! ! ! ! ! ! ! ! !
  • 43. ! ! ! ! !! ! 7 8 ctr INTEGER := 100000 ; 9 10 BEGIN 11 FOR idx IN 1..ctr LOOP 12 w_ids(idx) := idx; 13 w_nms(idx) := Widget || TO_CHAR(idx); 14 END LOOP; 15 16 FOR idx IN 1..ctr LOOP 17 INSERT INTO widgets VALUES (w_ids(idx), w_nms(idx)); 18 END LOOP; 19 20 END; 21 / PL/SQL procedure successfully completed. Elapsed: 00:00:21.71 ! SQL> alter session set tracefile_identifier = FORALL; Session altered. SQL> exec dbms_monitor.session_trace_enable; PL/SQL procedure successfully completed. SQL> SQL> SQL> DECLARE 2 TYPE NumTab IS TABLE OF widgets.widget_id%TYPE INDEX BY BINARY_INTEGER; 3 TYPE NameTab IS TABLE OF widgets.widget_nm%TYPE INDEX BY BINARY_INTEGER; 4 5 w_ids NumTab; 6 w_nms NameTab; 7 8 ctr INTEGER := 100000 ; 9 10 BEGIN 11 FOR idx IN 1..ctr LOOP 12 w_ids(idx) := idx; 13 w_nms(idx) := Widget || TO_CHAR(idx); 14 END LOOP; 15 16 FORALL idx IN w_ids.FIRST .. w_ids.LAST 17 INSERT INTO widgets VALUES (w_ids(idx), w_nms(idx)); 18 19 20 END; 21 / PL/SQL procedure successfully completed. Elapsed: 00:00:00.40!! ! ! ! 1!
  • 44. ! ! ! !!! W!(>6&!%@-45G%K!5$/?%&&6;!"88K888!Wi3ES:&!6)6V6)7-GG+!V%$&7&!5$/?%&&6;!(>%4!6!*7GJ!7&6;!-!kFSIPP!6?$%-&%&!(>$/7;>57(!B$/4!-55$/@64-(%G+!aK188!$/A&!5%$!&%?/)!(/!/V%$!a1cK888!$/A&!5%$!&%?/)f!S%&5/&%!(64%!)$/55%)!B$/4!"eLeD!&%?/)&!(/!8L"eD!&%?/)&L!S/A^*+^$/A!6&!1$>,%,)$-A!&G/A!*+!&G/Af!XBfB7 FQ"/5N+]&@3%#$&*)^()&2.&D.&KH"2&"&3%#$N+&()&32"2+/+#2&0.6ND&D.&M>%!(>%!-(65-((%$!-55%-$&!6!(>6&!B/$4K!6(!6&!(+56?-GG+!$//(%)!6!(>%!)%V%G/5%$U&!5$/?%)7$-G!A-+!/B!(>6J6;!&/!6(!6&!-!/BB&>//(!/B!(>%!N]7&(!B/GG/A6;!5$/?%)7$%Q!-(65-((%$!-&!A%GGL!:>%!4-6!)6BB%$%?%!*%(A%%!(>6&!B/$4!/B!(>%!-(65-((%$!-)!(>%!$/A^*+^$/A!5$/?%&&6;!&>/A!6!(>%!5$%V6/7&!%@-45G%!6&!(>-(!(>6&!B/$4!(+56?-GG+!)/%&U(!)/!-+!&5%?6-G!/$!?/45G%@!4-657G-(6/!/B!(>%!$/A&!6(!5$/?%&&%&L!!! W!(>6&!%@-45G%K!A%U$%!$%V6%A6;!&/4%!?/)%!(>-(!(>%!)%V%G/54%(!(%-4!-(!M-G4-$(!_(>%+!>-V%!/V%$!0!46GG6/!%45G/+%%&!A/$G)A6)%`!?$%-(%)!(/!&%(!-!-7-G!*/7&!-4/7(!B/$!%-?>!%45G/+%%L!:>%!(-*G%!*%6;!75)-(%)!?/(-6&!-!$/A!B/$!%-?>!%45G/+%%!(>-(!$%?%6V%)!-!-7-G!*/7&!G-&(!+%-$L!Y7(K!6B!-!%45G/+%%!A-&!>6$%)!&6?%!G-&(!+%-$U&!*/7&%&!A%$%!5-6)K!-!$/A!B/$!(>%4!A6GG!%%)!(/!*%!6&%$(%)L!IGG!%45G/+%%&!A6GG!$%?%6V%!-!*/7&!%X76V-G%(!(/!1n!/B!(>%6$!-7-G!&-G-$+L!:>%!)%V%G/5%$!A$/(%!(>%!B/GG/A6;!5$/?%)7$%H! declare v_ct number := 0 ; cursor emp_cur is select emp_id, salary from wal_emps where status = ACTIVE; begin for rec in emp_cur loop begin select count(emp_id) into v_ct from annual_bonus where emp_id = rec.emp_id; if v_ct > 0 then update annual_bonus set bonus_amt = rec.salary * .03 where emp_id = rec.emp_id ; else insert into annual_bonus values (rec.emp_id, rec.salary * .03); end if; exception when others then dbms_output.put_line (sqlerrm) ; end ; end loop ; end ; /!! ! ! ! ! ! ! ! ! ! ! !
  • 45. ! ! ! ! !! !! M>%!%@%?7(%)K!7&6;!-!"8K888!$/A!&7*&%(K!(>6&!6&!(>%!$%&5/&%!(64%!5$/B6G%H! !! :/!%@%?7(%!(>6&!5$/?%&&!B/$!"8K888!$/A&!6(!(//J!-G4/&(!e!&%?/)&L!:>-(!4-+!/(!&%%4!(>-(!*-)!-(!B6$&(!;G-?%K!*7(!A>-(U&!;/6;!(/!>-55%!A>%!6(!$7&!B/$!-GG!0!46GG6/!%45G/+%%&R!i/(!/G+!)/%&!(>6&!?/)%!*G/?J!%@>6*6(!(>%!N&G/A!*+!&G/AQ!-(65-((%$K!6(U&!]7&(!5G-6!-AB7G!B/$!&%V%$-G!$%-&/&L!:>%!B6$&(!(>6;!(>-(!>-55%&!6&!-!?/7(!X7%$+K!A>/&%!57$5/&%!6&!(/!)%(%$46%!6B!(>%!%45G/+%%!>-&!-!$/A!-G$%-)+!%@6&(6;!6!(>%!-7-Gj*/7&!(-*G%K!6&!%@%?7(%)L!WB!(>-(!6&!($7%K!-!T#<I:E!6&!%@%?7(%)K!/(>%$A6&%!-!Wi3ES:!6&!%@%?7(%)L!3/K!/(!/G+!6&!%-?>!T#<I:E!/$!Wi3ES:!*%6;!%@%?7(%)!/%!-(!-!(64%K!-!3EPEC:!&(-(%4%(!6&!%@%?7(%)!(/!)%(%$46%!A>6?>!&(-(%4%(!&>/7G)!*%!%@%?7(%)L!! :>6&!3EPEC:!?/7(_p`!X7%$+!G6J%G+!)%&%$V%&!-!-(65-((%$!-GG!6(&!/A!_G%(U&!?-GG!6(!(>%!N)/A!B/$!(>%!?/7(Q!-(65-((%$`f!W(!6&!?/45G%(%G+!7%?%&&-$+!-)!&>/7G)!*%!$%4/V%)L!W(U&!7%?%&&-$+!&6?%!/!4-((%$!A>6?>!&(-(%4%(!+/7!%@%?7(%!B6$&(K!6B!6(!B-6G&!(/!%@%?7(%!*-&%)!/!%6(>%$!-!<T#jgIPjFijWi<s!%$$/$!6B!(>%!Wi3ES:!($6%&!(/!6&%$(!-!$/A!(>-(!-G$%-)+!%@6&(&K!/$!-!iFj<I:IjkFTi<!%$$/$!6!(>%!?-&%!/B!(>%!T#<I:EK!(>%!%@?%5(6/!>-)G%$!?/7G)!?-(?>!(>%!%$$/$!-)!%@%?7(%!(>%!/(>%$!&(-(%4%(!5$/5%$G+L!! I!&645G%!-G(%$-(6V%!(>-(!-!)%V%G/5%$!46;>(!(>6J!/B!6&!(/!7&%!-!.ESdE!&(-(%4%(L!:>%!.ESdE!A/7G)!*%!-!&6;G%!&(-(%4%(!(>-(!A/7G)!5$/5%$G+!>-)G%!(>%!Wi3ES:&!-)!T#<I:E&!-55$/5$6-(%G+L!! SQL> MERGE INTO annual_bonus B 2 USING ( 3 SELECT emp_id, salary 4 FROM wal_emps 5 WHERE status = ACTIVE) E 6 ON (B.emp_id = E.emp_id) 7 WHEN MATCHED THEN 8 UPDATE SET B.bonus_amt = E.salary * 0.03 9 WHEN NOT MATCHED THEN 10 INSERT (B.emp_id, B.bonus_amt) 11 VALUES (E.emp_id, E.salary * 0.03) 12 / 10000 rows merged.! ! ! ! a!
  • 46. ! ! ! !! Y+!&645G+!?/V%$(6;!(>%!5$/?%)7$-GK!$/A^*+^$/A!5$/?%&&6;!(/!-!&6;G%!.ESdE!&(-(%4%(K!(>%!$%&5/&%!(64%!)$/55%)!B$/4!cLc"m!&%?/)&!(/!"LDc1!&%?/)&L!i/(!*-)L!Y7(K!6B!(>%+!(//J!-!G//J!-(!(>%6$!$%X76$%4%(&!-)!&(/55%)!(>6J6;!G6%-$G+K!(>%+!?/7G)UV%!($6%)!(>6&!6&(%-)H! SQL> create table annual_bonus_2011 as 2 select emp_id, salary * .03 as bonus_amt 3 from wal_emps 4 where status = ACTIVE; Table created.:>%!$%&5/&%!(64%!5$/B6G%!A/7G)!G//J!G6J%!(>6&H! !! :>%!?>/6?%!(/!?$%-(%!-!*$-)!%A!(-*G%!-)!*76G)!6(!)6$%?(G+!7&6;!-!CSEI:E!:IYPE!I3!A/7G)!;6V%!(>%4!(>%!$%&7G(!(>%+!%%)!A6(>/7(!(>%!-))6(6/-G!/V%$>%-)!(>-(!75)-(6;!(>%!%@6&(6;!(-*G%!$%X76$%&L!!! I&!WUV%!-G$%-)+!4%(6/%)!5$%V6/7&G+K!/%!/B!(>%!J%+&!(/!-V/6)6;!(>6&!-(65-((%$!6&!(/!;%(!-A-+!B$/4!(>%!>-*6(!/B!(>6J6;!5$/?%)7$-GG+L!:>%!4/$%!+/7!?-!(>6J!6!(%$4&!/B!&%(&!-)!A-+&!(/!-??/45G6&>!(-&J&!6!(>%!B%A%&(!&(%5&!5/&&6*G%K!(>%!%-&6%$!6(!A6GG!*%?/4%!(/!-V/6)!N&G/A!*+!&G/AQ!5$/?%&&6;L!XBg C#2%5"22+,#&>+0"5&W!>-V%U(!?/V%$%)!%V%$+!-(65-((%$!(>-(U&!/7(!(>%$%K!*7(!(>%&%!-$%!(>%!(/5!5$/*G%4!4-J%$&!W!&%%4!(/!&%%!4/&(!B$%X7%(G+L!F%!J%+!(/!B%$$%(6;!/7(!-+!-(65-((%$!6&!(/!&(%5!-A-+!B$/4!(>%!?/)%!-&!6(!6&!A$6((%!-)!?/&6)%$!>/A!+/7!A/7G)!-55$/-?>!(>%!&/G7(6/!-%AL!W(!6&!-!>-*6(K!-)!-!*-)!/%!-(!(>-(K!(/!(-J%!-!5//$G+!5%$B/$46;!3OP!&(-(%4%(!-)!&(-$(!($+6;!(/!(A%-J!6(!$-(>%$!(>-!(/!$%A$6(%!6(L!W(!6&!A-+!(//!%-&+!(/!B-GG!6(/!(>%!($-5!/B!!! D! ! ! ! ! ! ! ! ! ! !
  • 47. ! ! ! ! !! !G%((6;!/G)!B-46G6-$!A-+&!/B!)/6;!(>6;&!*G6)!+/7!(/!(>%!>6))%!($/7*G%&!A6(>6!(>/&%!/G)!A-+&L!:-J6;!(>%!(64%!(/!%V-G7-(%!3OP!B$/4!-!B$%&>!5%$&5%?(6V%!?-!;6V%!+/7$!46)!(>%!?>-?%!(/!4/$%!$%-)6G+!&%%!%A!&/G7(6/&!6&(%-)!/B!/G)!5$/*G%4&L!! ! ! ! c!
  • 48. ! ! ![ CU?@:&:1F&C@:1?>&,-$%!./$(/!6&!-!3$L!<YI!#%$B/$4-?%!{!:76;!35%?6-G6&(!B/$!k6)%G6(+!WB/$4-(6/!3%$V6?%&L!#$6/$!(/!>%$!?7$$%(!5/&6(6/!&>%!A-&!-!?/&7G(-(!-)!%)7?-(/$!&5%?6-G6[6;!6!-55G6?-(6/!/5(646[-(6/!6!*/(>!&>/7G)%$^(/^&>/7G)%$!?/&7G(6;!%;-;%4%(&!-)!?G-&&$//4!&%((6;&L!k/$!/V%$!08!+%-$&K!,-$%!>-&!A/$J%)!6!6B/$4-(6/!(%?>/G/;+!&(-$(6;!/7(!-&!-!4-6B$-4%!5$/;$-44%$K!)%V%G/5%$K!<YIK!)-(-!-$?>6(%?(K!$%&%-$?>%$K!%)7?-(/$!-)!?/&7G(-(L!2-V6;!7&%)!F$-?G%!&6?%!(>%!%-$G+!m8u&K!&>%!*%;-!(%-?>6;!/(>%$&!>/A!(/!7&%!F$-?G%!/V%$!-!)%?-)%!-;/L!3>%!6&!-!-7(>/$!/B!(>$%%!F$-?G%!*//J&!B$/4!I5$%&&K!-!B$%X7%(!&5%-J%$!-(!?/B%$%?%&!-)!7&%$!;$/75&K!-!F$-?G%!ICEK!-)!-!4%4*%$!/B!(>%!F-J:-*G%!%(A/$J!_-!6B/$4-G!-&&/?6-(6/!/B!qF$-?G%!&?6%(6&(&q!(>-(!-$%!A%GG!J/A!(>$/7;>/7(!(>%!F$-?G%!?/4476(+`L!!3>%!*G/;&!-(!>((5H==J-$%4/$(/L*G/;&5/(L?/4L!!!!! e! ! ! ! ! ! ! ! ! ! !
  • 49. ! ! ! ! !! !!! I55%)6@! I! ! C>-5(%$!D!B$/4!! E@5%$(!F$-?G%!#$-?(6?%&H!<-(-*-&%!I)466&($-(6/!B$/4!(>%!F-J!:-*G%! I5$%&&K!08"8!!! ! ! ! !
  • 50. ! ! !!! ! ! ! ! ! ! ! ! ! !
  • 51. CHAPTER 7■■■Managing SQL PerformanceWhat is the first thing you think of when you see the topic “Managing SQL Performance”? Do youthink of response time? Do you think of user complaints about the application running “too slow”?Do you think of AWR or ADDM reports? As far as users are concerned, performance is response time. Users don’t care about server anddatabase configurations, network bandwidth, I/O rates, or query execution plans. They care abouthow fast they perceive their applications run. All that other stuff is geek speak and doesn’t even blipon their radar. Regardless of whether or not all your monitoring gadgets flash green lights ofperfection, if your users are complaining, you’ve got a problem. The truth is, the seeds of thoseproblems very likely were planted when the code was first written.Adopting a Performance MindsetManaging the performance of your application SQL doesn’t start when your users begin tocomplain. It starts before the first statement is ever written. It starts when the business tasks thatyour application will need to service are defined. On a time line, that starting point and the firstuser complaint about performance could be quite far apart. But I absolutely believe that you haveto start by considering your user’s experience. If you start by thinking of how your user will experience your application, this implies thatmanaging SQL performance is first about a mindset, not a dataset. Your mindset is, in part, relatedto the set of rules you’ve internalized. But it’s also about your beliefs and feelings related to whatperformance is and means. Do you think managing performance is hard? Do you think managingperformance is, or isn’t, your responsibility? Do you think performance is something to think aboutlater, when, or if, problems arise? Do you think managing performance is about avoidingcatastrophes or about envisioning possibilities? Sometimes your mindset is influenced by your job description. If you have not specifically beentasked with performance as a concern, you may likely ignore, or at the very least minimize, yourrole in ensuring optimal performance of the SQL you write. But regardless of your defined job role, Ido believe that effective SQL performance management starts with your mindset. It’s how you viewyour role and the contributions you make in regard to the performance of your code that makes thedifference between an optimally performing application and a poorly performing one. 1
  • 52. CHAPTER 7 ■ MANAGING SQL PERFORMANCE Consider the definition of the word manage: 1: to handle or direct with a degree of skill: as a: to make and keep compliant b: to treat with care: husband c: to exercise executive, administrative, and supervisory direction of 2: to work upon or try to alter for a purpose 3: to succeed in accomplishing: contrive —Merriam-Webster Online www.merriam-webster.com/dictionary/manage This definition indicates that if you want something to be manageable, you must give it skilled attention and effort. So, first and foremost, I think managing performance is about integrating one simple principle into your mindset: I am responsible for the performance of the code I write or maintain. Without a conscious personal choice to accept responsibility for it, performance will not be manageable. To manage performance, you first need to know how and why Oracle determines the plan operations for each query. Then you need to be able to easily and accurately capture diagnostics indicating what your application code is doing as it executes. That means learning how Oracle’s cost- based optimizer works, particularly how it utilizes statistics. And it means understanding the importance of having your application well instrumented. The statistics used by the optimizer are like fuel for your car. The quality of the fuel you put into your vehicle affects how well your car handles, how much gas mileage it gets, how often it needs maintenance, and even how long your vehicle will be serviceable. Understanding what goes in to the optimizer so that it can choose which SQL execution plan operations are best helps you know what should reasonably be expected to occur. And if you don’t get the results you expect or get the performance you need, you can adjust the fuel. After you understand what goes in to the optimizer so it can make the best plan choices, you then need to be able to capture diagnostics quickly and accurately. There are many ways to capture diagnostic data, but managing performance well requires that you be able to easily collect the metrics you need, when you need them. The best way to do this is to properly instrument your code. Instrumentation is just a few extra lines of code you add to your application to enable you to identify the tasks it executes (that is, SQL related to business tasks) so they are easy to find and monitor. ■ Note Statistics and instrumentation are not covered here, but the “Further Reading” section at the end of this chapter lists several sources for more information. Hopefully, I’ve established so far that managing SQL performance starts with an attitude, a mindset. You accept responsibility for the performance of every statement you write or maintain. You build foundation knowledge about how the optimizer works and use that knowledge to feed the optimizer with quality statistics and quality code. You make your application easy to monitor by adding instrumentation that will help you get the right performance metrics when you need them. The bottom line is that your mindset is geared toward managing performance every day and not just when problems arise.2
  • 53. CHAPTER 7 ■ MANAGING SQL PERFORMANCEDefining and Measuring PerformanceNow that we’ve established the mindset, let’s talk about the dataset. How do you know whether the SQLyou write performs fast enough to be acceptable? My favorite, simple definition of performance is this: Fast now. Fast later. —Cary Millsap Performance is primarily related to time; how long does your SQL take to execute? But it is alsorelated to what your SQL does; what resources must be acquired to obtain the desired result?Performance is measurable, but often the problem is measuring the right thing. There are many ways to collect performance data. The key to managing performance efficiently is inknowing which ways provide you with the most accurate information possible with the least amount oftime and effort. Then, after you get the information, you need to know how to respond to it. Let’s say you are asked to write a SQL statement to retrieve aggregate totals of customer order data.You have a system-level agreement (SLA) stating that the query must execute in 4 seconds or less 95percent of the time. You write the query and measure how long it takes to execute by using yourwristwatch’s timer; the result is 3 seconds. Would you feel comfortable turning this code over toproduction? I’ve seen this method in use—really, I have. It’s a bit scary, isn’t it? The measurement accuracy ofyour trusty timepiece is only one reason this method scares me. As I mentioned, performance is a matterof measuring time, but it’s also a matter of resource use and scalability. I don’t think your watch caneffectively help you measure that. Although this is perhaps an extremely poor example of howperformance could be measured, there are other commonly used methods that are almost as bad. In the upcoming sections, I’ll review several methods for measuring performance and how eachmethod helps you manage, or not, your SQL’s performance.EXPLAIN PLANThe most often used method to review the performance characteristics of a query is the EXPLAIN PLANstatement. EXPLAIN PLAN displays the series of operations Oracle performs in order to run your SQLstatement. It provides information on the estimates of rows to be returned, the order of access and joinmethods, filter operations, and aggregations, as well as optimization information such as cost andestimated time to complete. However, there is one main problem with relying on EXPLAIN PLAN. The output lists what is supposedto happen when the statement executes, not what actually does happen. In Listing 7-1, note how Iexecute the first statement, and then check the shared pool for the actual execution plan by usingDBMS_XPLAN.DISPLAY_CURSOR. Next I execute the same statement using EXPLAIN PLAN and display the planusing DBMS_XPLAN.DISPLAY. The actual plan and the EXPLAIN PLAN do not match.Listing 7-1. Comparing Plan Output of EXPLAIN PLAN and DBMS_XPLANSQL>variable orgid numberSQL>exec :orgid := 1;PL/SQL procedure successfully completed. 3
  • 54. CHAPTER 7 ■ MANAGING SQL PERFORMANCE SQL>set serveroutput off SQL>SELECT AVG(BILL_SEQUENCE_ID) FROM BOM WHERE ORG_ID = :orgid ; AVG(BILL_SEQUENCE_ID) --------------------- 1 row selected. SQL>select * from table(dbms_xplan.display_cursor(null,null,ALLSTATS LAST 2 +PEEKED_BINDS -ROWS)); PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 8xbvq97cr6zx2, child number 0 ------------------------------------- SELECT AVG(BILL_SEQUENCE_ID) FROM BOM WHERE ORG_ID = :orgid Plan hash value: 1633877697 ------------------------------------------------------------------------------------ | Id | Operation | Name |Starts | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 1 |00:00.01 | 31 | | 1 | SORT AGGREGATE | | 1 | 1 |00:00.01 | 31 | | 2 | TABLE ACCESS BY INDEX ROWID| BOM | 1 | 0 |00:00.01 | 31 | |* 3 | INDEX SKIP SCAN | BOM_N1 | 1 | 0 |00:00.01 | 31 | ------------------------------------------------------------------------------------ Peeked Binds (identified by position): -------------------------------------- 1 - (NUMBER): 1 Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ORG_ID"=:ORGID) filter("ORG_ID"=:ORGID) 26 rows selected. SQL> SQL>explain plan for SELECT AVG(BILL_SEQUENCE_ID) FROM BOM WHERE ORG_ID = :orgid ; Explained. SQL>select * from table(dbms_xplan.display) ;4
  • 55. CHAPTER 7 ■ MANAGING SQL PERFORMANCEPLAN_TABLE_OUTPUT-------------------------------------------Plan hash value: 1639627616---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 8 | 1557 (2)| 00:00:19 || 1 | SORT AGGREGATE | | 1 | 8 | | ||* 2 | TABLE ACCESS FULL| BOM | 607K| 4744K| 1557 (2)| 00:00:19 |---------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - filter("ORG_ID"=TO_NUMBER(:ORGID))14 rows selected. Not only are the operations shown by each display function different, but you can see how theexplained version lists estimates for only Rows, Bytes, and Time. The actual data gives you a much moreaccurate view of what really happened. So why is the explained version so different? The reason for thisdifference is that EXPLAIN PLAN uses a different code path to determine the execution plan than does theoptimizer. That code path treats bind variables like strings and ignores their values. On the other hand,the optimizer considers the values of bind variables and may determine a different plan choice based onthose values. If you use EXPLAIN PLAN, you may believe that the plan will use a set of operations that it does not.And if you want to be successful in managing the performance of your SQL, you need to make decisionsbased on actual data, not on a “best guess.” The bottom line is that you can’t absolutely rely on EXPLAINPLAN to give you a clear picture of how your query is performing. So it shouldn’t be your only, or primary,tool for measuring SQL performance. It can’t truly measure performance. And if performance isn’tmeasurable, it likely isn’t going to be manageable. If you can’t measure it, you can’t manage it. —David GarvinDBMS_XPLANIn Listing 7-1, I used two functions to display execution plan output. Both functions are found in theDBMS_XPLAN supplied package. The DBMS_XPLAN package is used to format SQL execution plan output fromEXPLAIN PLAN, SQL stored in the AWR, SQL from a SQL tuning set, as well as for actual cached cursors.This package makes it easy to get a detailed and nicely formatted display of execution plan information. If you’re an old-timer, like me, you may still have an old script or two that you wrote to manuallyformat EXPLAIN PLAN output. There’s no longer any need for your old scripts, because this package(available since Oracle version 9) does all the work for you. It is flexible enough to handle every displayoption you need and will automatically display only relevant information. For example, if your plan usesparallel execution, the display function will show you that information. But if you don’t use parallel, thecolumns containing the data will not be included in the display. It’s a fantastic utility, and you can find a 5
  • 56. CHAPTER 7 ■ MANAGING SQL PERFORMANCE lengthy description of the package and the functions it contains in the Oracle PL/SQL Packages and Types Reference for your database version. For the examples throughout the rest of this chapter, I will use only the DBMS_XPLAN.DISPLAY_CURSOR function. This function is used to display execution plan output for any SQL loaded in the cursor cache. To use this function, you must have SELECT privilege on V$SQL, V$SQL_PLAN, and V$SQL_PLAN_STATISTICS. Note that these privileges are not granted by default to non-DBA users, and it may be necessary to specifically request that they be granted. The great thing about DISPLAY_CURSOR is that you get a very nicely formatted actual execution plan with, when requested, rowsource execution statistics. As long as you can locate the SQL statement whose execution plan and statistics you wish to view in the shared pool, you can retrieve and display the execution plan data. The way to call the function is to provide the sql_id and child_number for the SQL statement you want. The sql_id and child_number parameter values are identified in V$SQL (or V$SQLAREA or V$SQLTEXT). If you want to display the execution plan of the last statement executed in your session, you simply leave the parameters null. Listing 7-2 shows a simple example that illustrates a few key pieces of information that are output by DBMS_XPLAN.DISPLAY_CURSOR. Listing 7-2. Retrieving the sql_id and child_number Values for Use with DBMS_XPLAN.DISPLAY_CURSOR SQL>variable x number SQL>exec :x := 10 ; PL/SQL procedure successfully completed. SQL>select /*+ GATHER_PLAN_STATISTICS KM2 */ * from dept where deptno = :x; DEPTNO DNAME LOC --------------- -------------- ------------- 10 ACCOUNTING NEW YORK 1 row selected. SQL>SELECT xplan.* 2 FROM 3 ( 4 select max(sql_id) keep 5 (dense_rank last order by last_active_time) sql_id 6 , max(child_number) keep 7 (dense_rank last order by last_active_time) child_number 8 from v$sql 9 where upper(sql_text) like %&1% 10 and upper(sql_text) not like %FROM V$SQL WHERE UPPER(SQL_TEXT) LIKE % 11 ) sqlinfo, 12 table(DBMS_XPLAN.DISPLAY_CURSOR(sqlinfo.sql_id, sqlinfo.child_number, ALLSTATS LAST +PEEKED_BINDS -ROWS)) xplan 13 / Enter value for 1: KM26
  • 57. CHAPTER 7 ■ MANAGING SQL PERFORMANCEPLAN_TABLE_OUTPUT-------------------------------------SQL_ID 3h1bp5jsm6d7v, child number 0-------------------------------------select /*+ GATHER_PLAN_STATISTICS KM2 */ * from dept where deptno = :xPlan hash value: 3816518310-----------------------------------------------------------------------------------| Id | Operation | Name |Starts|A-Rows|A-Time |Buffers |-----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | 1|00:00.01| 2 || 1 | TABLE ACCESS BY INDEX RO| DEPT | 1| 1|00:00.01| 2 ||* 2 | INDEX UNIQUE SCAN | DEPT_DEPTNO_PK | 1| 1|00:00.01| 1 |-----------------------------------------------------------------------------------Peeked Binds (identified by position):-------------------------------------- 1 - (NUMBER): 10Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("DEPTNO"=:X) To make it easy to retrieve the sql_id and child_number and execute DISPLAY_CURSOR in the future, Isaved Listing 7-2’s query into a script and will execute it at the SQL*Plus command line by supplying myidentifying string as a command-line parameter each time I use it (for example, @pln KM2). Note also inListing 7-2, I added KM2 as my identifying string within the hint. Adding a simple identifier like this willhelp you quickly locate SQL you are testing. There are a few things to notice about the SQL I used to retrieve and display the plan: The GATHER_PLAN_STATISTICS hint: Notice that the SQL statement used in Listing 7-2 includes the GATHER_PLAN_STATISTICS hint. Using this hint is one way to make sure that Oracle correctly gathers rowsource execution statistics during your query execution. You may also set the STATISTICS_LEVEL parameter to ALL for your session, but I find that using the hint lets me gather the rowsource data only when I need it. The rowsource execution statistics are the actual data collected when the query executed. The collected values are displayed in the A-Rows (actual rows), A-Time (actual elapsed time), and Buffers (actual logical block reads) columns in Listing 7-2. These statistics are extremely valuable in determining exactly how the execution plan performed and where you need to focus your attention to optimize the query. The query used to retrieve the sql_id and child_number: I used the last_active_time column to order the information so that I get back only the most recent (MAX) sql_id and child_number that matches the sql_text pattern I enter. This works almost every time when I’m testing something, particularly if I use a unique identifier in the SQL statement I’m testing. However, if you happen to be looking for a pattern that matches more than one query text and yours wasn’t the last execution, you may not get your plan, but someone else’s. The more specifically you can identify your query, the more likely it is this query will give you the correct plan. If you find you have trouble, you can 7
  • 58. CHAPTER 7 ■ MANAGING SQL PERFORMANCE simply query V$SQL for a list of all SQL that matches a certain pattern. Then you can visually identify the correct statement and pass the exact sql_id and child_number into the DISPLAY_CURSOR call. The format parameters used in the DISPLAY_CURSOR call: The DISPLAY_CURSOR call takes a third parameter named FORMAT. There are numerous options to choose for this parameter value. The default is TYPICAL, but I used a set of options that displayed the data I wanted to show for this example. The use of the ALLSTATS LAST +PEEKED_BINDS –ROWS options causes the actual rowsource execution statistics for the last execution to be displayed along with the values for bind variables used in the SQL, and leaves out the estimated rows column (E-Rows). Extended SQL Trace Data The Oracle database is instrumented to provide a play-by-play of exactly where your code spends its time. This feature (event 10046) can be enabled on demand by using several methods. The output is a text file that contains two basic types of information: database calls (DB calls) and operating system calls (OS calls). DB call lines begin with the tokens PARSE, EXEC, or FETCH, and each represents a single completed call to the database by the Oracle kernel. OS call lines begin with the token WAIT and represent a single completed call to the operation system by the Oracle kernel. There are also lines that begin with the token STAT that contain the execution plan data. These lines are unformatted, but equivalent to the output you’d get by using DBMS_XPLAN.DISPLAY_CURSOR to retrieve plan data from the cursor cache. The trace data can be aggregated and summarized to provide a complete response time profile of your code’s execution. That means that you can know exactly where every bit of execution time consumed by your query was used. With trace data, you can get a more complete picture of your query’s response time. The STAT lines give you the rolled-up totals for the query plan and rowsource execution statistics, but you also get the detailed DB calls and any OS calls that contributed to the response time as well. If you want the definitive tool for helping you diagnose a performance problem, extended SQL trace data gets my vote. In nearly ten years of using trace data and the response time profiles created from them, I have not encountered a performance issue that the trace data didn’t reveal. I know my experience cannot speak to every possible circumstance, and I admit to hearing others speak of several issues where trace data was of little or no assistance. But in my experience, you can’t beat the value of trace data when you want to manage SQL performance. In Listing 7-3, I use extended SQL trace data to locate a problem that wasn’t visible when examining only the plan data displayed using DBMS_XPLAN.DISPLAY_CURSOR. First, the query: select * from bom where item_id=11 and org_id=2; I executed the query with extended SQL tracing turned on and produced a simple response time profile. The total response time was 1.00 second. ■ Note I used a simple Perl script to create the profile, but Method R Corporation has a software product called the Profiler that can produce response time profiles and is a phenomenal tool for this purpose. Visit http://method-r.com/software/profiler-info for more information.8
  • 59. CHAPTER 7 ■ MANAGING SQL PERFORMANCEListing 7-3. A Response Time Profile Generated from Extended SQL Trace DataResponse Time Component Duration Pct # Calls Dur/Call---------------------------------------- --------- ------ --------- ------------SQL*Net message from client 0.52s 51.9% 12151 0.000043sCPU service 0.30s 29.8% 12155 0.000024sunaccounted-for 0.16s 16.2% 1 0.160985sSQL*Net message to client 0.02s 2.2% 12151 0.000002s---------------------------------------- --------- ------ --------- ------------Total response time 1.00s 100.0% I then used DBMS_XPLAN.DISPLAY_CURSOR to review just the execution plan data, as shown in Listing 7-4.Listing 7-4. Using DISPLAY_CURSOR to Display Execution Plan Data------------------------------------------------------------------------------------| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers |------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 24294 |00:00.10 | 24472 || 1 | TABLE ACCESS BY INDEX ROWID| BOM | 1 | 24294 |00:00.10 | 24472 ||* 2 | INDEX RANGE SCAN | BOM_N1 | 1 | 24294 |00:00.02 | 12208 |------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ITEM_ID"=11 AND "ORG_ID"=2) Just so you can also see how this information looks in the trace file, Listing 7-5 shows the STAT lines.Listing 7-5. STAT Lines from the Extended SQL Trace DataSTAT #6 id=1 cnt=24294 pid=0 pos=1 obj=71478 op=TABLE ACCESS BY INDEX ROWID BOM(cr=24472 pr=0 pw=0 time=100007 us cost=285 size=1481934 card=24294)STAT #6 id=2 cnt=24294 pid=1 pos=1 obj=71480 op=INDEX RANGE SCAN BOM_N1(cr=12208 pr=0 pw=0 time=39970 us cost=60 size=0 card=24294) Now what? Is 1 second acceptable? Well, I expect this query to execute hundreds or thousands oftimes every hour, and it is not reasonable for a single execution to take a second. But if you look at theplan statistics, you’ll notice that the A-Time column is showing only 1 centisecond of elapsed timeconsumed to access 1,252 buffers and retrieve 24,294 rows. A centisecond seems reasonable. It appearsthat the correct index was used because the index returned only the rowids that the parent table accessstep acquired and kept. But why did my response time profile’s actual elapsed time of 1 second notmatch the time shown in the execution plan? It looks like one or the other is wrong, doesn’t it? The truth is that both of the timings are correct. The problem is that we assumed both timingsmeasure the same thing, and they do not. To be more precise, the centisecond timing shown for the planexecution is included in the 1 second total response time. The time shown in the A-Time columnrepresents the time it took to complete the plan operations: an index range scan and a TABLE ACCESS BYINDEX ROWID. That means there are other events that are not included in the plan execution displayprovided through DBMS_XPLAN.DISPLAY_CURSOR. 9
  • 60. CHAPTER 7 ■ MANAGING SQL PERFORMANCE However, if you look at the response time profile, you can clearly see that the majority of the time was spent doing 12,151 SQL*Net message from client calls. That call indicates that the database currently isn’t doing anything, but rather is waiting to be told what to do. So can you guess why all those calls are being made? It’s due to the number of rows each FETCH call is limited to return in a single retrieval. In SQL*Plus, this value is set with a parameter called ARRAYSIZE. In this example, ARRAYSIZE was set to 2. That means that only 2 rows at a time are sent to the client. Because we had more than 24,000 rows to be returned, more than 12,000 network roundtrips were required to get the entire result set back to the client application. But would we really want so many round trips to happen? What if ARRAYSIZE were set to a higher value? If ARRAYSIZE was set to 100, for example, then 100 rows per FETCH call would be retrieved and sent to the client. Therefore, given that we have approximately 24,000 total rows to be returned, it would be necessary to make about 240 calls to do so. I can now forecast how much of a response time reduction I can get if I make this change. Roughly, if only 240 SQL*Net message from client calls are made instead of more than 12,000, I can estimate the time to make those calls will reduce from 0.52 seconds (12,151 calls taking 0.000043 seconds each) to approximately 0.01 seconds (240 calls). That’s simple enough, and it looks like a significant response time difference. Listing 7-6 shows the response time profile for the same query executed after I changed the ARRAYSIZE parameter to 100. Listing 7-6. The Response Time Profile After the ARRAYSIZE Change Response Time Component Duration Pct # Calls Dur/Call ---------------------------------------- --------- ------ --------- ------------ SQL*Net message from client 0.14s 70.1% 247 0.000549s CPU service 0.05s 24.2% 251 0.000186s unaccounted-for 0.01s 5.5% 1 0.010728s SQL*Net message to client 0.00s 0.2% 247 0.000002s ---------------------------------------- --------- ------ --------- ------------ Total response time 0.19s 100.0% That’s better! My estimate was a little bit off because the duration per call was higher for this test than for the original, but I was pretty much on target with what I expected to happen. Being able to see the entire performance picture, not just one piece of it, and then accurately forecast what will happen if you make a change is the real magic of using extended SQL trace. I could continue to experiment with ARRAYSIZE to locate the best setting, but for my purpose here, this is good enough. The point is that with just the plan execution information I reviewed by using DBMS_XPLAN.DISPLAY_CURSOR, I couldn’t fully diagnose the problem. With just that portion of the total picture, I was missing a critical piece of information that I needed. After I had that information, it was a simple matter to see where my time was being used and find a way to reduce it. So why not just use extended SQL trace all the time? Well, in some cases, it’s more difficult to use it and get access to the generated trace files than it is to just grab the plan execution information quickly from the cursor cache. When tracing, you want to make sure to properly scope the trace so you capture only the data for the task you care about. Capturing extra activity that you don’t care about can distort the response time profile so your task is masked within a bunch of other unimportant stuff. Also, in order to retrieve the trace file, you must have permission to access the dump file directory on your database server and then have a tool (either one you create or one you purchase) that can create a response time profile for you. Sometimes working with and around those limitations makes the use of extended SQL trace require more time and effort than some people are willing to expend. Just remember that you have multiple tools in your performance toolbox. Use the tool that’s appropriate for the task at hand. The key is to know when to use which tool. One of my favorite sayings is10
  • 61. CHAPTER 7 ■ MANAGING SQL PERFORMANCE“Why guess when you can know?” And because I want to know exactly where all my response time isgoing, I find using extended SQL trace invaluable. Just remember that in order to manage SQLperformance well, you want to know, not just guess.Interpreting Performance DataAfter you execute your query and collect the performance data, what’s next? If you can get theinformation but don’t know how to respond to what you see, you’re really no further along towardsolving the problem. It’s often easiest to learn by example, so I’m going to review four cases thatdemonstrate common problems I see over and over. I’ll walk you through each example and point outhow to interpret what the performance data is telling you.Case 1: The Lack of a Good IndexOne performance problem I run into quite frequently is caused by the absence of an index that properlycovers the query predicate. There may be many indexes on the table, but none of them provide theoptimal coverage for the query in question. Many times the available indexes are for only a singlecolumn, but the query predicate includes several columns. So even if the optimizer chooses to use asingle-column index, a table block access will be required to retrieve the row and then apply the otherfilter conditions before the determination to keep the row for the result set can finally be made. The plan execution data provides you with a clear indication of when the index being used couldbenefit from having additional columns. In Listing 7-7, I display only two lines, along with just their A-Rows values and the related predicate information lines, from a very long plan to point out how the indexin use isn’t very effective.Listing 7-7. Excerpt of Execution Plan When a “Good” Index Does Not Exist-----------------------------------------------------------------------| Id | Operation | Name | A-Rows |-----------------------------------------------------------------------|* 32 | TABLE ACCESS BY INDEX ROWID | GL_ACCOUNT_INSTANCE | 606K||* 33 | INDEX UNIQUE SCAN | GL_ACCOUNT_INSTANCE_PK | 3183K|Predicate Information (identified by operation id):--------------------------------------------------- 32 - filter(("GLI"."GL_ACCT_STAT_CD"=ACTIVE AND"TD"."GL_ACCT_NAME_CD"="GLI"."GL_ACCT_NAME_CD")) 33 - access("TD"."GL_SYS_ID"="GLI"."GL_SYS_ID") Notice how the index range scan shows a large number of rowids being passed to the parent tableaccess step (more than 3.1 million), but less than 20 percent of those rows (606,000) are retained for thefinal result set. Now look at the Predicate Information for the parent table access step (Id = 32). Twocolumns have to be obtained from the row in the data block and then filtered before the row is finallyaccepted or rejected. If those two columns were added to the index, or if a new index with all threecolumns was added, 80 percent of the work currently being performed to access all the data blocks thatultimately get thrown away would be avoided. In Listing 7-8, I show the difference in the plan after thenew index is created. 11
  • 62. CHAPTER 7 ■ MANAGING SQL PERFORMANCE Listing 7-8. Excerpt of Execution Plan When a “Good” Index Does Exist ------------------------------------------------------------------------ | Id | Operation | Name | A-Rows | ------------------------------------------------------------------------ | 32 | TABLE ACCESS BY INDEX ROWID | GL_ACCOUNT_INSTANCE | 606K| |* 33 | INDEX RANGE SCAN | GL_ACCOUNT_INSTANCE_IX5 | 606K| Predicate Information (identified by operation id): --------------------------------------------------- 33 - access("TD"."GL_SYS_ID"="GLI"."GL_SYS_ID" AND "GLI"."GL_ACCT_STAT_CD"=ACTIVE AND "TD"."GL_ACCT_NAME_CD"="GLI"."GL_ACCT_NAME_CD") It was easy to see how having the filter conditions applied at the parent table access step caused more work to occur. The more often an index can provide complete coverage for the conditions in your SQL, the less work you incur to get the final result set. It may not always be possible to create an index to cover your predicates completely. However, if performance for a particular query is critical, you’ll want to make sure that indexes provide the highest coverage possible. Case 2: The Presence of Unidentified Data Skew Query response times can vary significantly depending on the plan operations chosen by the optimizer. The optimizer depends on statistics to be able to determine the best plan choices. If the available statistics do not accurately represent your data, the optimizer’s estimates for plan choice may result in operations that aren’t as performance optimal as needed. A quick review of plan execution data lets you see how the optimizer’s estimates stack up to the actual usage. Listing 7-9 shows the execution plan data for a query that requests only data where the object_type column contains the value ‘PROCEDURE’. Listing 7-9. Execution Plan for Query Using object_type = ‘PROCEDURE’ ------------------------------------------------------------------------------------ | Id | Operation | Name |E-Rows |A-Rows |A-Time |Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 4416 |00:00.01 | 1586 | | 1 | TABLE ACCESS BY INDEX R| B | 59403 | 4416 |00:00.01 | 1586 | |* 2 | INDEX RANGE SCAN | B_OBJTYPE_IDX | 59403 | 4416 |00:00.01 | 105 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_TYPE"=PROCEDURE) Compare the E-Rows and A-Rows columns in Listing 7-9. It’s pretty obvious that there is a significant discrepancy between the estimate and the actual values (over 13 times difference). But, the response time, of approximately 1 centisecond, wasn’t a problem. If I used only EXPLAIN PLAN output, I wouldn’t have noticed this difference at all and may have stopped my analysis right there. But look at Listing 7-10 to see what happens when you use a different object_type value for the same query.12
  • 63. CHAPTER 7 ■ MANAGING SQL PERFORMANCEListing 7-10. Execution Plan for Query Using object_type = ‘SYNONYM’-----------------------------------------------------------------------------------| Id | Operation |Name |E-Rows |A-Rows |A-Time |Buffers |-----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | 858K|00:18.88 | 62952 || 1 | TABLE ACCESS BY INDEX R|B | 59403 | 858K|00:18.88 | 62952 ||* 2 | INDEX RANGE SCAN |B_OBJTYPE_IDX | 59403 | 858K|00:00.86 | 19441 | -----------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("OBJECT_TYPE"=SYNONYM) Ouch! This time the response time is almost 19 seconds. The plan is the same, an index range scan,but when the query returns more data than estimated, the response time is now unacceptable. You canalso see that not only has the response time increased, but the buffers have increased significantly aswell. This makes sense because the query retrieved more than 850,000 rows. There’s quite a difference between 1,586 buffer gets and 62,952 buffer gets for the two queries.However, there is an even more significant difference that you don’t see. There is a statistic called bufferis pinned count that is viewable only if you snapshot that specific statistic name from V$SESSTAT beforeand after you execute your query and then diff the results. That means you won’t see it when usingDISPLAY_CURSOR or even in extended SQL trace data. This statistic contains a count of buffer accesses for blocks previously pinned into the cache. Thefact that those blocks are already pinned means there is less overhead to access them and requires lesswork on Oracle’s part (particularly less latching). The main point I want to make is that the Bufferscount is only part of the whole picture for an index access operation. Don’t forget that more work isbeing done! In this case, the buffer is pinned count value for this query is 1,655,993. That means over 1.7million buffers were accessed to satisfy the query result. No wonder it took so long! As I said, the bufferis pinned count statistic isn’t directly included in either extended SQL trace output or from the cursorcache. You have to compute it yourself for a single query execution. Although knowing about thisstatistic isn’t critical to how you’d respond to what you see in this execution plan, I think it is importantto know there is more data available that completes the picture of the work this query is doing. If you’d like to be able to view statistics such as buffer is pinned count, capture latch statistics, andmore, there are two sets of utility scripts that I use frequently to to do this: Tom Kyte’s runstats package(http://asktom.oracle.com/pls/asktom/f?p=100:8:0::NO) and the Hotsos SQL Test Harness(www.hotsos.com/educ_downloads.html). Both sets of scripts are easy to install and use, and help youcollect even more performance data you can use. The bottom line in this example is that the optimizer didn’t have the correct information to knowthat there was a skewed distribution of values in the object_type column. By default, statistics aregathered assuming that all data values are uniformly distributed. If that is not the case, statistics must begathered specifically to capture skew. Skew is captured by the creation of a histogram and is done usingthe METHOD_OPT parameter when gathering object statistics as follows:SQL> exec dbms_stats.gather_table_stats (user,B,estimate_percent=>100,method_opt=>for columns object_type); 13
  • 64. CHAPTER 7 ■ MANAGING SQL PERFORMANCE Listings 7-11 and 7-12 show how after the histogram is in place, the estimates for the two queries are accurate. Also, the plan choices are appropriate for each predicate, not to mention that the response time for the second query improves significantly. Listing 7-11. Execution Plan for Query Using object_type = ‘PROCEDURE’ with Histogram in Place ------------------------------------------------------------------------------------ | Id | Operation | Name |E-Rows |A-Rows |A-Time |Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 4416 |00:00.01 | 1586 | | 1 | TABLE ACCESS BY INDEX R| B | 4416 | 4416 |00:00.01 | 1586 | |* 2 | INDEX RANGE SCAN | B_OBJTYPE_IDX | 4416 | 4416 |00:00.01 | 105 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_TYPE"=PROCEDURE) Listing 7-12. Execution Plan for Query Using object_type = ‘SYNONYM’ with Histogram in Place ------------------------------------------------------------------------------------ | Id | Operation | Name | E-Rows | A-Rows | A-Time | Buffers | Reads | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 858K|00:00:03.49 | 49242 | 22224 | |* 1 | TABLE ACCESS FULL| B | 858K| 858K|00:00:03.49 | 49242 | 22224 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("OBJECT_TYPE"=SYNONYM) Although this is a very simple example of how the presence of data skew can cause the optimizer estimates to be orders of magnitude off, the ability to compare estimated and actual values using DBMS_XPLAN.DISPLAY_CURSOR makes the issue easy to spot and correct quickly. Finding the presence of skew isn’t the only time when having the estimated vs. actual comparison will pay off. But the point is that regardless of the cause, the ability to see both values at a glance makes it obvious if there is an issue at all. Case 3: SQL That Should Be Rewritten In some cases, you’ll find that the performance problem you’re reviewing can be fixed without touching the code, as you’ve seen in the previous examples. In my experience, however, often the best fix is to rewrite the SQL. Of course, if you can’t touch the code, you’ll have to find another way around, such as using stored outlines or SQL profiles. But even if you can’t change the code as the final solution, you may need to modify the code in order to determine the best execution plan possible so you can save and enable it easily.14
  • 65. CHAPTER 7 ■ MANAGING SQL PERFORMANCE Listing 7-13 shows a seemingly simple query, but after reviewing the performance data, you’ll seethat rewriting it would significantly improve its performance.Listing 7-13. Query and Execution Plan with an Easy-to-Miss Scalability IssueSELECT ATTR_FCTR, ATTR_FCTR_YR, ATTR_FCTR_MO, PROJECT_CODE FROM PRJ_ATT_FACTORS A WHERE SIM_YR || SIM_MO = (SELECT MAX(B.SIM_YR || B.SIM_MO) FROM PRJ_ATT_FACTORS B WHERE A.PROJECT_CODE = B.PROJECT_CODE);-----------------------------------------------------------------------------------| Id | Operation | Name |Starts |A-Rows |A-Time | Buffers |-----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 16 |00:00.01 | 71 ||* 1 | FILTER | | 1 | 16 |00:00.01 | 71 || 2 | TABLE ACCESS FULL | PRJ_ATT_FACTORS | 1 | 25 |00:00.01 | 8 || 3 | SORT AGGREGATE | | 9 | 9 |00:00.01 | 63 ||* 4 | TABLE ACCESS FULL| PRJ_ATT_FACTORS | 9 | 25 |00:00.01 | 63 |-----------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("SIM_YR"||"SIM_MO"=) 4 - filter("B"."PROJECT_CODE"=:B1) This particular query has a subquery in the WHERE clause that returns the MAX year/month for a givenproject code. So for each row in PRJ_ATT_FACTORS, the subquery will execute as the row is filtered throughthe WHERE clause. That’s not precisely true, because subquery caching comes into play. Subquery cachinghas the effect of requiring that the subquery be executed just once per distinct project code instead ofonce per row.■ Note A wealth of information on subquery caching is available by doing a simple Google search on Oraclesubquery caching. Consider the ground that must be covered to obtain the final result set. My test table has 25 rows (Id= 2, A-Rows = 25). For those 25 rows, Oracle executes the MAX subquery nine times (Id = 3, Starts = 9).Because of subquery caching and because there are only nine distinct project codes in my table, itexecutes only nine times. After a project code is used in the subquery once, its result is retained inmemory and reused, and doesn’t require Oracle to issue the subquery again. But the point is that thesubquery gets executed over and over again as new project codes occur. At this point, you may be wondering why I don’t just create an index on the project_code column sothat instead of the subquery plan doing a full table scan, it would use the index. I could do that. But evenif I create the index and it improves things, by reducing buffer gets and therefore likely time as well, the 15
  • 66. CHAPTER 7 ■ MANAGING SQL PERFORMANCE query will still be making repeated executions of the subquery. I want to find a way to avoid the repeated executions. Also notice that the subquery is against the same table I’m accessing in the outer query. So the primary question I’d want to consider is “Can I write this query differently to avoid multiple accesses against the same table over and over?” Right now, the way the query is written, there’s not much that can be done to make it scale very well. It may perform okay now, but what about when the volume of data grows? Listing 7-14 shows what happens if I double the table size to 50 rows. Listing 7-14. Execution Plan When the Data Size (Number of Rows) in the Test Database Doubles ----------------------------------------------------------------------------------- | Id | Operation | Name |Starts |A-Rows |A-Time | Buffers | ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 32 |00:00.01 | 127 | |* 1 | FILTER | | 1 | 32 |00:00.01 | 127 | | 2 | TABLE ACCESS FULL | PRJ_ATT_FACTORS | 1 | 50 |00:00.01 | 8 | | 3 | SORT AGGREGATE | | 17 | 17 |00:00.01 | 119 | |* 4 | TABLE ACCESS FULL| PRJ_ATT_FACTORS | 17 | 50 |00:00.01 | 119 | ----------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("SIM_YR"||"SIM_MO"=) 4 - filter("B"."PROJECT_CODE"=:B1) The number of executions of the subquery increases from 9 to 17 (check the Starts column), and the buffers accessed increases from 71 to 127. Just to give you an idea of how bad this gets as volume increases, Listing 7-15 shows this same query’s plan execution data from production; the table has more than 270,000 rows. Listing 7-15. Execution Plan from Production ------------------------------------------------------------------------------------ | Id | Operation |Name |Starts |A-Rows | A-Time |Buffers | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 18480 |04:13:58.24 | 52756K| |* 1 | FILTER | | 1 | 18480 |04:13:58.24 | 86529 | | 2 | TABLE ACCESS FULL |PRJ_ATT_FACTORS| 1 |271830 |00:00:01.53 | 3053 | | 3 | SORT AGGREGATE | |142578 | 28843 |04:13:11.10 | 52667K| |* 4 | TABLE ACCESS FULL |PRJ_ATT_FACTORS|142578 | 14816K|04:11:33.55 | 52667K| ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("SIM_YR"||"SIM_MO"=) 4 - filter("B"."PROJECT_CODE"=:B1) In production, the response time for this query was more than 4 hours! So, how could I rewrite this query to eliminate the need to query the same table over and over, and do it only once? How about using16
  • 67. CHAPTER 7 ■ MANAGING SQL PERFORMANCEan analytic function? Listing 7-16 shows the rewritten query and the new plan execution data using mytest environment with a 50-row table.Listing 7-16. Rewritten Query and Execution PlanSELECT ATTR_FCTR, ATTR_FCTR_YR, ATTR_FCTR_MO, PROJECT_CODE, THE_YRMO FROM ( SELECT MAX(SIM_YR || SIM_MO) OVER (PARTITION BY PROJECT_CODE) AS THE_MAX, ATTR_FCTR, ATTR_FCTR_YR, ATTR_FCTR_MO, PROJECT_CODE, SIM_YR || SIM_MO AS THE_YRMO FROM PRJ_ATT_FACTORS ) aWHERE a.THE_YRMO = THE_MAX ;------------------------------------------------------------------------------------| Id | Operation |Name |Starts |A-Rows | A-Time |Buffers |------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 32 |00:00:00.01 | 7 ||* 1 | VIEW | | 1 | 32 |00:00:00.01 | 7 || 2 | WINDOW SORT | | 1 | 50 |00:00:00.01 | 7 || 3 | TABLE ACCESS FULL|PRJ_ATT_FACTORS | 1 | 50 |00:00:00.01 | 7 |------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("A"."THE_YRMO"="THE_MAX") This rewritten version of the query requires only a single access on the table. Much better! Listing 7-17 shows how the rewritten query performed in production.Listing 7-17. Rewritten Query’s Production Execution Plan------------------------------------------------------------------------------------| Id | Operation |Name |Starts |A-Rows | A-Time |Buffers |------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 18480 |00:00:11.47 | 1833 ||* 1 | VIEW | | 1 | 18480 |00:00:11.47 | 1833 || 2 | WINDOW SORT | | 1 |271830 |00:00:09.73 | 1833 || 3 | TABLE ACCESS FULL|PRJ_ATT_FACTORS | 1 |271830 |00:00:01.59 | 1826 |------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("A"."THE_YRMO"="THE_MAX") 17
  • 68. CHAPTER 7 ■ MANAGING SQL PERFORMANCE I’d say this is a very successful optimization effort! The response time decreased from more than 4 hours to a little more than 11 seconds. The most difficult part of this problem was determining how to rewrite the query. That part gets easier with practice, but it is important to stay on top of new coding features and syntax options that are available in the version of Oracle you are using. SQL like this has often been around for a long time, and it’s easy to see the code only as it is and not think of new possibilities for how it could be written more efficiently. Almost every SQL statement can be written in multiple ways. Just make sure that when you are considering ways to write SQL, your options aren’t limited by a lack of knowledge. Sometimes overcoming not knowing what you can do is the biggest performance hurdle you’ll have to cross. Case 4: SQL That Unnecessarily Invokes PL/SQL The issue of concern in this case is called context switching. SQL is a nonprocedural language and has a separate execution code path, often referred to as the engine, within the Oracle kernel. PL/SQL is a procedural language and has its own execution engine. In order for a SQL statement to call a PL/SQL code block, or a PL/SQL code block to execute a SQL statement, Oracle must switch between execution engines. This switch means extra overhead is incurred that would not otherwise be required if the switch did not happen. This “hit,” even if it is very small, say 1/1000th of a second, will add up if you do it enough. For example, take a SQL statement that returns 10,000 rows. If each of those result rows has a PL/SQL function call, that would mean 10 seconds of your response time would be consumed just executing those calls (10,000 rows × 0.001 seconds). Can you really afford that extra response time consumption? Before you jump to the conclusion that I’m making a blanket statement that PL/SQL is bad for performance and should be avoided, let me stop you. I am absolutely not saying that. What I want you to know is that if you have a need to execute a PL/SQL code block that provides you with a result you cannot achieve directly through SQL, you will pay a performance price for using it. So one thing to look for when your SQL performance is suffering is the presence of PL/SQL calls when you could get the same result another way. The tricky part about this issue is that if you look only at the SQL execution plan data, you won’t see the problem, except perhaps in terms of response time. But in your test environment where you may have only small tables to query against, even response time may not be poor enough to alert you. Listing 7-18 shows a PL/SQL function and two queries we’ll use to walk through an example. Listing 7-18. Example Queries and PL/SQL Function create or replace function get_ord_tot(p_ordno IN number) return number as v_tot number(13,2); begin select sum(total_order_item_price) into v_tot from items where order_no = p_ordno; return v_tot; exception when others then return 0; end; /18
  • 69. CHAPTER 7 ■ MANAGING SQL PERFORMANCEselect cust_no, order_no, get_ord_tot(order_no)from ordersgroup by cust_no, order_no;select o.cust_no, o.order_no, sum(i.total_order_item_price)from orders o, items iwhere o.order_no = i.order_nogroup by o.cust_no, o.order_no; In the first query, the function GET_ORD_TOT is called to retrieve the total order amount, whereas inthe second query, the same result is achieved using a table join. Listings 7-19 and 7-20 list the executionplan data for each query.Listing 7-19. Execution Plan Data for a Query Using a PL/SQL Function------------------------------------------------------------------------------| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers |------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 12890 |00:00:00.02 | 156 || 1 | HASH GROUP BY | | 1 | 12890 |00:00:00.02 | 156 || 2 | TABLE ACCESS FULL| ORDERS | 1 | 12890 |00:00:00.01 | 156 |------------------------------------------------------------------------------Listing 7-20. Execution Plan Data for a Query Using a Table Join-----------------------------------------------------------------------------------| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers |-----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 12890 |00:00:00.10 | 436 || 1 | HASH GROUP BY | | 1 | 12890 |00:00:00.10 | 436 ||* 2 | HASH JOIN | | 1 | 12890 |00:00:00.08 | 436 || 3 | TABLE ACCESS FULL | ORDERS | 1 | 12890 |00:00:00.01 | 156 || 4 | VIEW | VW_GBC_5 | 1 | 12890 |00:00:00.08 | 280 || 5 | HASH GROUP BY | | 1 | 12890 |00:00:00.08 | 280 || 6 | TABLE ACCESS FULL| ITEMS | 1 | 70975 |00:00:00.01 | 280 |-----------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("O"."ORDER_NO"="ITEM_1") Compare both listings. At a glance, Listing 7-19 appears to be better in terms of overall time (A-Time)and logical I/O (Buffers). But with just a bit more scrutiny, you should notice that the first query plandoesn’t contain any operations involving the ITEMS table. Huh? Did using the function call just give thatdata access to you for free? Obviously, it did not. What the function call did was to effectively hide theaccess on the ITEMS table from your view. Execution plans show only a single query’s data. Queries thatcall PL/SQL that contains additional SQL will not be included in the execution plan data for the queryyou executed. The execution plan data for the second query using the table join contains everything you 19
  • 70. CHAPTER 7 ■ MANAGING SQL PERFORMANCE need, but you need more data for the first query. So if you compare just these two listings, you’re really not comparing the complete picture of both executions. To get a complete picture of each query execution for comparison, this is a case where you can benefit from collecting extended SQL trace data. Recall that with trace data you get all the execution data, including time spent waiting for events that don’t show up in the plan data alone. So for each test, I collected trace data and created response time profiles, as shown in Listings 7-21 and 7-22. Listing 7-21. Response Time Profile for a Query Using a PL/SQL Function Response Time Component Duration Pct # Calls Dur/Call ---------------------------------------- --------- ------ --------- ------------ CPU service 3.04s 76.3% 281 0.010826s SQL*Net message from client 0.82s 20.7% 270 0.003050s unaccounted-for 0.10s 2.6% 1 0.104507s pipe get 0.02s 0.4% 1 0.015347s SQL*Net message to client 0.00s 0.0% 270 0.000002s ---------------------------------------- --------- ------ --------- ------------ Total response time 3.99s 100.0% Listing 7-22. Response Time Profile for a Query Using a Table Join Response Time Component Duration Pct # Calls Dur/Call ---------------------------------------- --------- ------ --------- ------------ SQL*Net message from client 0.84s 79.5% 270 0.003109s CPU service 0.11s 10.3% 281 0.000389s unaccounted-for 0.07s 6.9% 1 0.072339s pipe get 0.03s 3.2% 1 0.034077s SQL*Net message to client 0.00s 0.0% 270 0.000002s ---------------------------------------- --------- ------ --------- ------------ Total response time 1.06s 100.0% From the two profiles in Listings 7-21 and 7-22, note in particular the total time spent executing CPU service calls. When using the PL/SQL function, 281 calls take 3.04 seconds to complete. But when using a table join, the same number of calls takes only 0.11 seconds. Also notice the difference in duration per call: 0.010826 seconds per call using the function as compared to 0.003109 seconds per call for the join. With this data, it appears pretty obvious that using the PL/SQL function has significantly greater impact than execution plan data alone seemed to indicate. To take it one step further, Listing 7-23 shows the output from the Oracle utility tkprof I used to summarize the trace file containing the PL/SQL function. With this summarization, I can show you where the “missing” function calls and their related data are. Listing 7-23. tkprof Output Excerpt SQL ID: buy1cavrwf8ju Plan Hash: 1902515569 SELECT SUM(TOTAL_ORDER_ITEM_PRICE) FROM ITEMS WHERE ORDER_NO = :B120
  • 71. CHAPTER 7 ■ MANAGING SQL PERFORMANCEcall count cpu elapsed disk query current rows------- ------ -------- ---------- ---------- ---------- ---------- ----------Parse 1 0.00 0.00 0 0 0 0Execute 12890 1.66 1.53 0 0 0 0Fetch 12890 0.21 0.16 0 39124 0 12890------- ------ -------- ---------- ---------- ---------- ---------- ----------total 25780 1.87 1.69 0 39124 0 12890 The main query execution plan in Listing 7-19 showed only the access to the ORDERS table (12,890rows). Using the trace data, we can look further into exactly what happened when that query executed.We can see that for each of those 12,890 rows, the query against the ITEMS table in the function wasexecuted using the ORDER_NO as the input parameter (:B1). Note that I’m not showing you exactly the amount of time accounted for by context switching. It isincluded in the CPU service time required to execute the function call over and over. But when you addup the overall effect of executing all those function calls plus the overhead of switching between the SQLand PL/SQL engine to do them, I think you get the picture! I’ll end by saying that the use of functions such as the one demonstrated here is most often done inthe name of reusability or ease of maintenance. The argument is that if you know you’ll want to use thatsame query against the ITEMS table in many places and if you put it in a function, you’ll have only oneplace to make a change should one be required. I disagree with the premise of this argument that theability to reuse or maintain application code is the first priority. PL/SQL is a procedural languageextension to SQL; SQL is the core. If you’ve accepted the performance mindset as your own, youwouldn’t choose to do anything that would degrade performance at the expense of perceived savings inmaintaining that SQL. The more you code big blocks of PL/SQL that could be written in one SQLstatement, you’ve added more code to maintain, added more complexity and opportunity for bugs, andcertainly added overhead that will hit your application every day and not just during a maintenancecycle. If performance is your goal, doing everything you can in SQL directly should be your first choice.SummaryTo manage SQL performance well requires a commitment to the process. Beginning with your mindset,you accept responsibility for the performance of every SQL statement you write or maintain. A big partof fulfilling your responsibility is to keep your education up-to-date. You must know how to accuratelycollect and analyze performance data to move quickly and efficiently from problem diagnosis to asolution. It’s not really that hard to get the data you need. We’ve reviewed a couple of ways in this chapter.Regardless of the method you use to collect and review performance data, the key is to stop guessingabout performance problems. Remember: Why guess when you can know? You won’t be able to count on every SQL performance problem you encounter being somethingyou’ve seen before. There are certainly common problems that can, and do, occur. But as you grow moreadept at managing SQL performance, you’ll find that you no longer make the mistakes that lead to thosekinds of problems in the first place. The key is to be able to pinpoint the cause of the problem quickly. Ifyou don’t know exactly how to proceed after you’ve identified the problem, a little bit of research shouldlead you to the information you need to finalize a solution. Optimal performance doesn’t just happen. Nor is it that hard to accomplish, even though manypeople believe it is. To achieve consistently high-performing SQL requires time, knowledge, anddiligence. To do it well, you need to integrate concern for performance into your daily routine. After 21
  • 72. CHAPTER 7 ■ MANAGING SQL PERFORMANCE you’ve made SQL performance management part of your routine, you’ll likely find that the performance issues you face will be fewer and easier to deal with when they do occur. Further Reading Wolfgang Breitling, “Tuning by Cardinality Feedback,” www.centrexcc.com/Tuning%20by%20Cardinality%20Feedback.pdf Wolfgang Breitling, “SQL Tuning with Statistics,” www.centrexcc.com/SQL%20Tuning%20with%20Statistics.pdf Cary Millsap, “For Developers: Making Friends with the Oracle Database,” http://method-r.com/downloads/doc_download/10-for-developers-making- friends-with-the-oracle-database-cary-millsap Karen Morton, “Managing Statistics for Optimal Query Performance,” http://method-r.com/downloads/doc_download/11-managing-statistics-for- optimal-query-performance-karen-morton Karen Morton, “Performance Instrumentation for PL/SQL,” http://method- r.com/downloads/doc_download/8-performance-instrumentation-for-plsql- when-why-how-karen-morton22
  • 73. ! ! ! ! !! ! ! ! I55%)6@! Y! ! C>-5(%$!"a!B$/4!! #$/!F$-?G%!3OP! I5$%&&K!08"8!! ! ! ! !
  • 74. ! ! !!! ! ! ! ! ! ! ! ! ! !
  • 75. CHAPTER 15■ ■ ■Testing and Quality AssuranceRobyn SandsAs youve worked through the chapters of this book, you may have written some code to test theexamples. And since you chose this particular book instead of a “Welcome to SQL” style book, its likelythat you had written quite a few SQL statements before you ever picked this book up. As youve read thisbook, did some of the chapters remind you of your prior work? If so, how did you feel about the codeyouve written in the past? If youre like most developers, there were times when you thought, “Hey, considering how little Iknew about this functionality back then, I did pretty well.” And there may have been a few times whenyou cringed a bit, realizing that something you were very proud of at the time wasnt such a greatapproach after all. Dont worry; we all have applications that we would write completely differently if weonly knew then what we know now. Besides, its always easier to write better code with hindsight visionor as an armchair code jockey. If the code you write today is better than the code you wrote yesterday, you’re continuing to growand learn, and that is commendable. Realizing our older work could have been done better is aninevitable part of the learning process. As long as we learn from our mistakes and do it a little better withthe next application or the next bit of code, were moving in the right direction. It’s also true that we need to be able to measure the quality of our current code now, not five yearsfrom now when weve grown even wiser. We want to find the problems in our code before thoseproblems affect our users. Most of us want to find all the errors or performance issues before anyoneelse even sees our work. However, while that kind of attitude may indicate an admirable work ethic, itsnot an advisable or even achievable goal. What we can achieve is a clear definition what a specific pieceof code needs to accomplish and how we will prove that the code meets the defined requirements.Code should have measurable indicators of success that can prove or disprove the fact that we have metour goal. So what are those measurable factors? While the target measurement will vary depending on theapplication, there are several basic requirements for all application code. First and foremost, the codeneeds to return accurate results and we need to know that results will continue to be accuratethroughout the system’s life cycle. If end users cannot count on the data returned by a databaseapplication, that’s a pretty serious failure. Performance is another measurable attribute of our code. The target run times will be highlydependent on the application in question: a database used by the home owners association to trackwho has paid their annual fees is not required to perform at the same level as a database containing thecurrent stock quotes, but the methods used to compare execution plans and measure run time can bethe same. Code quality requires that we understand the application requirements, the function beingperformed, and the strengths and weaknesses of the specific system. Testing should focus on verifyingfunctionality, pushing the weakest links to their breaking point, and recording all measurements alongthe way. 465
  • 76. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCETest CasesFor the examples in this chapter, you will be working with the same Order Entry sample schema that youused for the transaction processing examples in Chapter 14. You will make more changes to yourschema, adding new data and altering views and reports. You will begin by defining the changes to bemade and the tests you will use to verify the success of those changes. So here is the backstory: one of your suppliers, identified only as “Supplier 103089” in the database,is changing their product numbers for the software you purchase from them to resell to your customers.The new identifiers are appended with a - and a two character value to identify the software packagelanguage. For example, the suppliers product identifier for all English software packages will end in “-EN”. The supplier will require their product identifier to be referenced for ordering, software updates,and warranty support. The new product identifiers have an effective date of October 10, 2010. This change presents the following challenges for your company: • The Order Entry schema includes the supplier’s identifier in the PRODUCT_INFORMATION table, but the supplier product identifier is not stored in the sample schema database at all. You will alter the order entry schema to add this field and create a numerical value to serve as the current supplier product id. These changes can be considered a prerequisite to the changes instituted by your supplier. • Once you have added an initial supplier product identifier for all the products you sell, you need to determine how you will add the modified product identifiers for this one supplier. You also need to have a method of controlling the effective date of the new identifiers. • The purchasing department uses an inventory report to determine which products are getting low on stock. This report will need to reflect the current supplier product identifier until October 10, 2010. After that date, the report should print the new supplier product identifier so the purchasing agent can place and verify orders easily. • The order entry system will continue to use your internal product identifier when orders are received from your customers. Orders and invoices must show your product identifier and name, plus the supplier product identifier. • You have inventory on hand that is packaged with the current supplier product identifier. You can continue to sell those products as-is but your customer invoices must show the actual supplier product ID found on the packaging. This means your inventory system must treat the items labeled with the new numbering scheme as a distinct product. As you make these changes, there are several basic tests and quality issues to consider. The pointsthat follow are not intended to be all-inclusive as every system will have its own unique testrequirements; however, there are some quality checks that can be applied to all systems. You’ll use thefollowing points as a starting point: • All objects that were valid before your changes should be valid when your changes are complete. Views, functions, procedures, and packages can be invalidated by a table change, depending on how the code for those objects was originally written. You will check for invalid schema objects both before and after you make your changes. Objects that are invalidated as an indirect result of your planned modifications should recompile successfully without further changes.466
  • 77. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE • All data changes and results output must be accurate. Verifying data can be one of the more tedious tasks when developing or altering a database application, and the more data in the system, the more tedious the work will be. Its also the most critical test your code must past: if the data is not accurate, it doesnt matter if the other requirements have been met or how fast the code executes. If the data being stored or returned cannot be trusted, your code is wrong and you’ve failed the most basic requirement. The simplest approach is to break data verification into manageable components, beginning by verifying the core data set, and then gradually expanding the test to the more unique use cases (the “edge cases”) until you are certain all data is correct. • Query performance can be verified by comparing the before and after versions of the execution plan. If the execution plan indicates the process has to work harder after your modifications, you want to be sure that additional work is, in fact, required and not the result of a mistake. Use of execution plans was addressed in detail in Chapter 6 so refer back to that chapter for more information on the topic plus tips on making the best use of the information found in the execution plan. Later in this chapter, I will discuss code instrumentation and the Instrumentation Library for Oracle(ILO). ILO uses Oracle’s DBMS_APPLICATION_INFO procedures. While it is possible to use theDBMS_APPLICATION_INFO procedures on their own, ILO makes it very easy and straightforward to addinstrumentation to your code. Ive added some additional functionality to the ILO package; the updatesare available for download at Apress. Once your code is instrumented, these additional modules make itpossible to build test systems that record processing times as you make iterative changes to your code orsystem configuration. This performance data will make it very clear when your changes have had apositive impact on processing times and when you might want to consider another approach.Testing MethodsThere are as many different approaches to software testing as there are software development—andthere have quite possibly been an equal number of battles fought over both topics. Although it may beslightly controversial in a database environment, Im going to advocate an approach known as TestDriven Development (TDD). Test Driven Development originated in the realm of extreme programmingso you will need to make some modifications to the process to make it effective for databasedevelopment, but it offers some very genuine benefits for both new development and modificationefforts. In TDD, the developer begins by creating simple, repeatable tests that will fail in the existing systembut will succeed once the change is implemented correctly. This approach has the following benefits: • In order to write the test that will fail, you will have to thoroughly understand the requirements and the current implementation before you even begin to write application code. • Building the unit test script first ensures that you start by working through the logic of the necessary changes, thereby decreasing the odds that your code will have bugs or need a major rewrite. • By creating small, reusable unit tests to verify the successful implementation of a change, you build a library of test scripts that can be used both to test the initial implementation of the change and to confirm that the feature is still operating as expected as other system changes are made. • These small unit test scripts can be combined to create larger integration-testing scripts or become part of an automated test harness to simplify repetitive testing. 467
  • 78. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE • TDD assists in breaking changes or new development into smaller, logical units of work. The subsets may be easier to understand and explain to other developers, which can be especially important when project members are not co-located. • When test design is delayed until after development, testing frequently ends up being shortchanged, with incomplete or poorly written tests due to schedule constraints. Including test development efforts in the code development phases results in higher quality tests that are more accurate. As acknowledged earlier, TDD needs some adjustments in a database environment or you run therisk of building yet another black box database application that is bound to fail performance andscalability testing. Whenever you are developing or modifying an application that stores or retrievesinformation from a database, as you are preparing those first unit tests, you must consider the datamodel or work with the individual(s) responsible for that task. In my (sometimes) humble opinion, thedata model is the single most important indicator of a database application’s potential to perform.The schema design is crucial to the application’s ability to scale for more users, more data, or both. Thisdoes not mean that development cannot begin until there is a flawless entity-relationship model, but itdoes mean that the core data elements must be understood and the application tables should be welldesigned for at least those core elements. And if the database model is not fully developed, then buildthe application using code that will not result in extensive changes as the data model is refactored. So what exactly am I suggesting? To put it bluntly, if your application schema will continue to bedeveloped progressively, use procedures and packages for your application code. This will allow thedatabase to be refactored as data elements are moved or added, without requiring major front end coderewrites.■NOTE This has been far from a complete explanation of Test Driven Development or database refactoring. Istrongly recommend the book Refactoring Databases: Evolutionary Database Design by Scott W. Ambler andPramodkumar J. Sadalage for a look at database development using Agile methods. If you are interested ininformation specifically on TDD, you are welcome to contact me directly for additional references. But let’s get back to your application changes, shall we? In the case of the changing supplierproduct identifier, you begin by asking some questions. How will this new data element be used by yourcompany and your employees? How will this change impact your order entry and inventory data? Willthis change impact systems or processes beyond your order entry system? At minimum, yourpurchasing agents need the suppliers current product identifier to place an order for new products.Depending on how well recognized the component is, the supplier’s product identifier could be usedmore widely than one might expect. A specific product or component may even be a selling point withyour customers. A great example is CPUs: the make and the model of the processor in the laptop can befar more important than the brand name on the case. If this is true for the products you are reselling,the suppliers product id may be represented throughout multiple systems beyond the ordering system,so it would be necessary to extend your evaluation to include additional systems and processes.Unit TestsAs noted in the previous section, your first goal will be to write the unit tests you need to demonstratethat your application modifications are successful. However, since this is a database application, youneed to determine where this data element belongs before you can even begin to write the first unit test.Although the Oracle-provided sample schemas are far from perfect, you cannot refactor the entire468
  • 79. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEschema in this chapter, so there will be many data design compromises in the examples. This can alsobe true in the real world: it is seldom possible to make all the corrections we know should be made. Thisis why correcting problems in the schema design can be a long, iterative process requiring very carefulmanagement.■NOTE Reminder: The focus for this chapter is testing methods. I’ll keep the examples as short as possible toavoid detracting from the core message. This means the examples do not represent production ready code, nor dothe sample schemas represent production ready data models. Considering the primary Order Entry functions that will make use of the supplier product identifier,you decide to store the supplier product id in the PRODUCT_INFORMATION table. This table containsother descriptive attributes about the product, and it is already used in the output reports that will nowneed to include your newest data element. These are not the sole considerations when deciding whereand how to store data, but for your purposes in this chapter, it will do. In the real world, the amount ofdata to be stored and accessed, which data values will read most frequently, and how often specific datavalues will be updated should all be considered prior to making decisions about where the data belongs. Once you’ve decided where you will keep the data, you can begin preparing the necessary unit testsfor your change. So, what are the unit tests that will fail before you’ve added the supplier’s product id toyour schema? Here’s a list of the unit tests you will complete in this chapter: • Include the supplier’s product id on individual orders and invoices. • Print the supplier’s product id on the open order summary report. • Print a purchasing report that shows the current supplier’s product id. If you have been using a TDD process throughout development, then there are likely to be severalgeneric unit tests that have already been written and may be appropriate to include in this round oftests. Typical verification tests may focus on the following tasks: • Confirm that all objects are valid before and after your changes. • Confirm that an insert will fail if required constraints are not met. • Verify that default values are populated when new data records are added. • Execute a new order transaction with and without products from this specific supplier. If you have been thorough in your initial evaluation and unit test development work, you will knowwhich tests are expected to fail. Other operations, such as the new order transaction I covered in the lastchapter, you would expect to succeed, as you did not note that any changes are required for a new order.Should the existing unit tests for creating a new order fail after your changes, it would indicate that youdid not analyze the impact of this latest change as thoroughly as you should have. Before you make any changes to the database objects, you should confirm the state of the existingobjects. Preferably, all objects will be valid before you start making changes. This is important as itensures that you are aware of any objects that were invalid prior to your changes, and it helps you torecognize when you are responsible for invalidating the objects. Listing 15-1 shows a query to check forinvalid objects and the result of the query. 469
  • 80. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEListing 15-1. Checking for Invalid Objects Prior to Altering Database ObjectsSQL> select object_name, object_type, last_ddl_time, status from user_objects where status != VALID;no rows selected Listing 15-2 shows your three unit test scripts. Each of these scripts represents a report that mustinclude the correct supplier product identifier as related to your internal product number. The first testcreates a report for a single order, which is essentially the customer’s invoice. The second test is thepurchasing report, which must print the correct supplier product identifier plus the inventory on hand.The third unit test is a complete listing of all open orders; it has been built using several views.Listing 15-2. Unit Test Scripts--- order_report.sqlset linesize 115column order_id new_value v_order noprintcolumn order_date new_value v_o_date noprintcolumn line_no format 99column order_total format 999,999,999.99BREAK ON order_id SKIP 2 PAGEBTITLE OFFcompute sum of line_item_total on order_idttitle left Order ID: v_order - right Order Date: v_o_date - skip 2spool logs/order_report.txtselect h.order_id ORDER_ID, h.order_date, li.line_item_id LINE_NO, li.supplier_product_id SUPP_PROD_ID, li.product_name, li.unit_price, li.discount_price, li.quantity, li.line_item_total from order_detail_header h, order_detail_line_items li where h.order_id = li.order_id and h.order_id = ‘&Order_Number’ order by h.order_id, line_item_id ;spool off--- purchasing_report.sql470
  • 81. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEbreak on supplier skip 1column target_price format 999,999.99set termout offspool logs/purchasing_report.txtselect p.supplier_id SUPPLIER, p.supplier_product_id SUPP_PROD_ID, p.product_name PRODUCT_NAME, i.quantity_on_hand QTY_ON_HAND, (p.min_price * .5) TARGET_PRICE from product_information p, inventories i where p.product_id = i.product_id and p.product_status = orderable and i.quantity_on_hand < 1000 order by p.supplier_id, p.supplier_product_id ;spool offset termout on--- order_reports_all.sqlset linesize 115column order_id new_value v_order noprintcolumn order_date new_value v_o_date noprintcolumn line_no format 99column order_total format 999,999,999.99BREAK ON order_id SKIP 2 PAGEBTITLE OFFcompute sum of line_item_total on order_idttitle left Order ID: v_order - right Order Date: v_o_date - skip 2select h.order_id ORDER_ID, h.order_date, li.line_item_id line_no, li.product_name, li.supplier_product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_total from order_detail_header h, order_detail_line_item li where h.order_id = li.order_idorder by h.order_id, li.line_item_id ; Listing 15-3 shows execution of your unit test scripts and the resulting (expected) failures. 471
  • 82. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEListing 15-3. Initial Unit Test ResultsSQL> @ order_report.sql li.supplier_product_id, *ERROR at line 2:ORA-00904: "LI"."SUPPLIER_PRODUCT_ID": invalid identifierSQL> @purchasing_report.sql order by p.supplier_id, p.supplier_product_id *ERROR at line 6:ORA-00904: "P"."SUPPLIER_PRODUCT_ID": invalid identifierSQL> @order_report_all.sql li.line_item_id line_no, li.product_name, li.supplier_product_id ITEM_NO, *ERROR at line 2:ORA-00904: "LI"."SUPPLIER_PRODUCT_ID": invalid identifier Unit tests are typically created for and executed from the application interface but it’s extremelyhelpful to create database-only unit tests as well. Having a set of scripts that you can run independentlyof the application code outside of the database will allow you to check database functionality before youhand new code over to the test team. And if the front-end application tests result in unexpected errors,you will already have information about a successful database level execution, which will help bothteams troubleshoot problems more efficiently.Regression TestsThe goal of regression testing is to confirm that all prior functionality continues to work as expected.You also must be certain that you do not re-introduce old issues (bugs) into your code as you implementnew functionality. Regression tests are most likely to fail when there has not been adequate source codecontrol so someone has inadvertently used an obsolete piece of code as their starting point. If unit tests were written for the existing functionality as the first step when the functionality wasdeveloped, those unit tests become the regression tests to confirm that each component of the system isstill working as expected. In your case, the tests used to verify the order transaction process can be usedto verify that orders will still be processed as expected. Although I’m cheating a bit, I’ll skip the re-execution of the order entry transactions as I spent many pages on this topic in the last chapter.Schema ChangesAs a prerequisite to executing your examples, you need to make several changes to your schema tosupport storing a supplier product number at all. You’ll add a new varchar2 column in thePRODUCT_INFORMATION table to store the SUPPLIER_PRODUCT_ID field for each item you sell.You’ll populate the new column with a value to represent the current supplier product ids for all the472
  • 83. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEproducts you sell, and you’ll use the DBMS_RANDOM package to generate these numbers. Once thisdata exists, your basic unit tests referencing the supplier product identifier should succeed. However, to support the concept of effective product ids, you will add new records to thePRODUCT_INFORMATION table using your supplier’s new identification values, a new internal productnumber with the same product description and pricing. While you could update the existing records,this would violate the requirement to accurately reflect the supplier’s product identifier shown on theproduct packaging in your warehouses. It would also result in changing historical data, since you’vealready sold copies of this software to other customers. Although the software in the package isunchanged, the fact that your supplier has relabeled it essentially creates a brand new product, which iswhy you need these new product records. The new records will be entered with a product status of“planned,” since the effective date is in the future. On the October 10, 2010, the new parts will be markedas “orderable” and the current parts will become “obsolete.” In order to manage the effective dates for the changing internal product identifiers, you will create anew table, PRODUCT_ID_EFFECTIVITY. You’ll also create a PRODUCT_ID sequence to generate yournew internal identifiers, making certain that your sequence begins at a higher value that any of yourexisting product records. Although I won’t cover it in this chapter, this table could be used by ascheduled process that would update the PRODUCT_STATUS field in the PRODUCT_INFORMATIONtable to reflect whether a product was planned, orderable, or obsolete. It is the change in product statusthat will trigger which supplier’s product id is shown on the purchasing report so the purchasing agentcan reference the correct number when placing new orders. Listing 15-4 shows the schema changes asthey are processed.Listing 15-4. Schema Changes and New Product DataSQL> alter table product_information add supplier_product_id varchar2(15);Table altered.SQL> update product_information set supplier_product_id = round(dbms_random.value(100000, 80984),0) ;288 rows updated.SQL> commit;Commit complete.SQL> create sequence product_id start with 3525 ;Sequence created.SQL> create table product_id_effectivity ( product_id number, new_product_id number, supplier_product_id varchar(15), effective_date date) ;Table created.SQL> insert into product_id_effectivity 473
  • 84. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE (select product_id, product_id.nextval, round(dbms_random.value(100000, 80984),0)||-|| substr(product_name, instr(product_name,/,-1,1)+1), 10-oct-10 from product_information, dual where supplier_id = 103089 and product_name like %/%) ;9 rows created.SQL> select * from product_id_effectivity ;PRODUCT_ID NEW_PRODUCT_ID SUPPLIER_PRODUC EFFECTIVE_DATE---------- -------------- --------------- ------------------- 3170 3525 93206-SP 0010-10-10 00:00:00 3171 3526 84306-EN 0010-10-10 00:00:00 3176 3527 89127-EN 0010-10-10 00:00:00 3177 3528 81889-FR 0010-10-10 00:00:00 3245 3529 96987-FR 0010-10-10 00:00:00 3246 3530 96831-SP 0010-10-10 00:00:00 3247 3531 85011-DE 0010-10-10 00:00:00 3248 3532 88474-DE 0010-10-10 00:00:00 3253 3533 82876-EN 0010-10-10 00:00:009 rows selected.SQL> commit ;Commit complete.SQL> insert into product_information ( product_id, product_name, product_description, category_id, weight_class, supplier_id, product_status, list_price, min_price, catalog_url, supplier_product_id) (select e.new_product_id, p.product_name, p.product_description, p.category_id, p.weight_class, p.supplier_id, planned, p.list_price, p.min_price, p.catalog_url, e.supplier_product_id474
  • 85. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE from product_information p, product_id_effectivity e where p.product_id = e.product_id and p.supplier_id = 103089) ;9 rows created.SQL> select product_id, product_name, product_status, supplier_product_id from product_information where supplier_id = 103089 order by product_id ;PRODUCT_ID PRODUCT_NAME PRODUCT_STATUS SUPPLIER_PRODUC---------- --------------------------------- -------------------- --------------- 3150 Card Holder - 25 orderable 3150 3170 Smart Suite - V/SP orderable 3170 3171 Smart Suite - S3.3/EN orderable 3171 3175 Project Management - S4.0 orderable 3175 3176 Smart Suite - V/EN orderable 3176 3177 Smart Suite - V/FR orderable 3177 3245 Smart Suite - S4.0/FR orderable 3245 3246 Smart Suite - S4.0/SP orderable 3246 3247 Smart Suite - V/DE orderable 3247 3248 Smart Suite - S4.0/DE orderable 3248 3253 Smart Suite - S4.0/EN orderable 3253 3525 Smart Suite - V/SP planned 93206-SP 3526 Smart Suite - S3.3/EN planned 84306-EN 3527 Smart Suite - V/EN planned 89127-EN 3528 Smart Suite - V/FR planned 81889-FR 3529 Smart Suite - S4.0/FR planned 96987-FR 3530 Smart Suite - S4.0/SP planned 96831-SP 3531 Smart Suite - V/DE planned 85011-DE 3532 Smart Suite - S4.0/DE planned 88474-DE 3533 Smart Suite - S4.0/EN planned 82876-EN20 rows selected. Once you’ve completed the necessary schema updates, your next step will be to check for invalidobjects again. All objects were valid when you ran your initial check, but now you have altered a tablethat is likely to be referenced by several other code objects in your schema. If those objects were codedproperly, you will be able to recompile them as-is and they’ll become valid again. If your code is sloppy(perhaps someone used a ‘select * from PRODUCT_INFORMATION’ clause to populate an object thatdoes not have the new field), then the recompile will fail and you’ll need to plan for more applicationmodifications. The unit test to look for invalid objects, plus the two recompiles that are required afteryour changes are shown in Listing 15-5. 475
  • 86. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEListing 15-5. Invalid Objects Unit Test and Object RecompileSQL> select object_name, object_type, last_ddl_time, status from user_objects where status != VALID;OBJECT_NAME OBJECT_TYPE LAST_DDL_ STATUS----------------------------------- ------------------- --------- -------GET_ORDER_TOTAL PROCEDURE 04-jul-10 INVALIDGET_LISTPRICE FUNCTION 04-jul-10 INVALIDSQL> alter function GET_LISTPRICE compile ;Function altered.SQL> alter procedure GET_ORDER_TOTAL compile ;Procedure altered.SQL> select object_name, object_type, last_ddl_time, status from user_objects where status != VALID;no rows selectedRepeating the Unit TestsOnce you’ve confirmed that your planned schema changes have been successfully implemented and allobjects are valid, it’s time to repeat the remaining unit tests. This time, each of the tests should executeand you should be able to verify that the supplier’s product id is accurately represented in the dataresults. Results from the second execution of the unit test are shown in Listing 15-6. To minimize thenumber of trees required to print this book, output from the reports will be abbreviated.Listing 15-6. Second Execution of Unit TestsSQL> @order_reportOrder ID:5041 Order Date: 13 Jul 2010 NO SUP_PROD_ID PRODUCT_NAME UNIT_PRICE DISC_PRICE QTY ITEM_TOTAL--- ----------- ------------------------- ---------- ---------- ---- ---------- 1 98811 Smart Suite - S4.0/DE 222.00 199.80 5 999.00SQL> @purchasing_report476
  • 87. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE SUPPLIER S_PRODUCT PRODUCT_NAME QTY_ON_HAND TARGET_PRICE---------- ------------ ----------------------- ----------- ------------ 103086 96102 IC Browser Doc - S 623 50.00 103088 83069 OSI 1-4/IL 76 36.00 103089 86151 Smart Suite - S4.0/EN 784 94.00 89514 Smart Suite - V/DE 290 48.00 92539 Smart Suite - V/EN 414 51.50 93275 Smart Suite - V/FR 637 51.00 95024 Smart Suite - S4.0/SP 271 96.50 95857 Smart Suite - V/SP 621 66.00 98796 Smart Suite - S3.3/EN 689 60.00 98811 Smart Suite - S4.0/DE 114 96.50 99603 Smart Suite - S4.0/FR 847 97.50.......SQL> @order_report_all.sqlOrder ID: 2354 Order Date: 14 Jul 2002ID PRODUCT_NAME ITEM_NO UNIT_PRICE DISCOUNT_PRICE QTY LINE_ITEM_TOTAL--- ------------------------ -------- ---------- -------------- ----- --------------- 1 KB 101/EN 94979 48.00 45.00 61 2,745.00 1 KB 101/EN 98993 48.00 45.00 61 2,745.00 1 KB 101/EN 85501 48.00 45.00 61 2,745.00.......Order ID: 5016 Order Date: 06 Jul 2010 ID PRODUCT_NAME ITEM_NO UNIT_PRICE DISCOUNT_PRICE QTY LINE_ITEM_TOTAL--- ------------------------ -------- ---------- -------------- ----- --------------- 1 Inkvisible Pens 86030 6.00 5.40 1000 5,400.00Order ID: 5017 Order Date: 06 Jul 2010 ID PRODUCT_NAME ITEM_NO UNIT_PRICE DISCOUNT_PRICE QTY LINE_ITEM_TOTAL--- ------------------------ -------- ---------- -------------- ----- --------------- 1 Compact 400/DQ 87690 125.00 118.75 25 2,968.75Order ID: 5041 Order Date: 13 Jul 2010 ID PRODUCT_NAME ITEM_NO UNIT_PRICE DISCOUNT_PRICE QTY LINE_ITEM_TOTAL--- ------------------------ -------- ---------- -------------- ----- --------------- 1 Smart Suite - S4.0/DE 98811 222.00 199.80 5 999.00 Take note that in each case where the product name shows a product that will be affected by yoursupplier’s new identifiers, your reports are still showing the current supplier identifier. That’s becausethese reports have all been executed as of a date prior to the October 10, 2010 effective date. What youhave not yet addressed in your testing is a mechanism to set products referencing the old supplierproduct identifiers to “obsolete” and to make your new products referencing the new supplier productidentifier “orderable.” After the effective date has passed, you need the purchasing report in particular 477
  • 88. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEto reference the new IDs. Order data should continue to represent the item ordered and shipped, whichwould not necessarily be determined by the effective date for the part number change. Instead, youwant your sales team to sell the older product first, so you would only begin to see the new productidentifiers on orders and invoices after the existing inventory was depleted. This thought processshould trigger the development of a few more unit tests, such as testing the process to alter productstatus after a product change effectivity date had passed and confirming that the Order Entry system willnot make the new product identifiers available for purchase until the old stock has been depleted.Execution Plan ComparisonOne of the best tools available for evaluating the impact of the changes you make to database objectsand code is the execution plan. By recording the execution plan both before and after your changes, youhave a detailed measurement of exactly how much work the database needs to complete in order toprocess requests for the data in the past and how much work will be required to process those samerequests in the future. If the comparison of the before and after versions of the execution plan indicatesthat a significant amount of additional work is required, it may be necessary to reevaluate the code tosee if you can optimize it. If you find the process is already as optimized as it can be, you can then usethe information to nicely explain to the users that their report may take longer in the future due to theadditional functionality. Once you express your findings in those terms, you will discover exactly howmuch the users value that new functionality, and it will be up to them to decide if the changes areimportant enough to move to production. Comparing the execution plans can also make it very clear when there is something wrong with aquery. If you find that a process is working much harder to get the data, but the new changes don’tjustify the additional work, there is a strong possibility that there is an error in the code somewhere. For the next example, you will review the execution plans of the complete order report from yourunit testing. The execution plan recorded before you made any changes to the database is shown inListing 15-7. The scripts to gather the execution plans are based on the approach demonstrated inChapter 6.Listing 15-7. Order Report Execution Plan (Before)alter session set statistics_level = ALL;set linesize 105column order_id new_value v_order noprintcolumn order_date new_value v_o_date noprintcolumn ID format 99column order_total format 999,999,999.99BREAK ON order_id SKIP 2 PAGEBTITLE OFFcompute sum of line_item_total on order_idttitle left Order ID: v_order - right Order Date: v_o_date - skip 2spool logs/order_report_all_pre.txt478
  • 89. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEselect /* OrdersPreChange */ h.order_id ORDER_ID, order_date, li.line_item_id ID, li.product_name, li.product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_total from order_detail_header h, order_detail_line_items li where h.order_id = li.order_id order by h.order_id, li.line_item_id ;spool offset lines 150spool logs/OrdersPreChange.txt@pln.sql OrdersPreChangePLAN_TABLE_OUTPUT------------------------------------------------------------------------------------------SQL_ID ayucrh1mf6v4s, child number 0-------------------------------------select /* OrdersPreChange */ h.order_id ORDER_ID, order_date,li.line_item_id ID, li.product_name, li.product_id ITEM_NO,li.unit_price, li.discount_price, li.quantity, li.line_item_totalfrom order_detail_header h, order_detail_line_items li whereh.order_id = li.order_id order by h.order_id, li.line_item_idPlan hash value: 3662678147-------------------------------------------------------------------------------------------| Id |Operation |Name |Starts |E-Rows |A-Rows |Buffers |-------------------------------------------------------------------------------------------| 0 |SELECT STATEMENT | | 1 | | 417 | 29 || 1 | SORT ORDER BY | | 1 | 474 | 417 | 29 ||* 2 | HASH JOIN | | 1 | 474 | 417 | 29 || 3 | TABLE ACCESS FULL |PRODUCT_INFORMATION| 1 | 297 | 297 | 16 || 4 | NESTED LOOPS | | 1 | 474 | 417 | 13 || 5 | MERGE JOIN | | 1 | 474 | 417 | 9 ||* 6 | TABLE ACCESS BY INDEX ROW|ORDERS | 1 | 79 | 79 | 2 || 7 | INDEX FULL SCAN |ORDER_PK | 1 | 114 | 114 | 1 ||* 8 | SORT JOIN | | 79 | 678 | 417 | 7 || 9 | TABLE ACCESS FULL |ORDER_ITEMS | 1 | 678 | 678 | 7 ||* 10 | INDEX UNIQUE SCAN |ORDER_STATUS_PK | 417 | 1 | 417 | 4 |-------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("OI"."PRODUCT_ID"="PI"."PRODUCT_ID") 6 - filter("O"."SALES_REP_ID" IS NOT NULL) 479
  • 90. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE 8 - access("O"."ORDER_ID"="OI"."ORDER_ID") filter("O"."ORDER_ID"="OI"."ORDER_ID") 10 - access("O"."ORDER_STATUS"="OS"."ORDER_STATUS")35 rows selected. The order report is generated by joining two views: the order header information and the order lineitem details. You’ll assume the report is currently running fast enough to meet user requirements andthat there are no indicators that the quantity of data in the underlying tables is expected to increasedramatically in the future. The report is deemed as meeting requirements and the execution plan shallbe saved for future reference. This order report was executed as one of your first unit tests to verify that your unit tests work asexpected. After you made the required database changes, you executed the order report again andconfirmed that it completed. The report also seems to complete in about the same amount of time as itdid in the past. But let’s take a look at the latest execution plan to see how the report is reallyperforming. The post-change execution plan is shown in Listing 15-8.Lising 15-8. Order Report Execution Plan (After)alter session set statistics_level = ALL;set linesize 115column order_id new_value v_order noprintcolumn order_date new_value v_o_date noprintcolumn ID format 99column order_total format 999,999,999.99BREAK ON order_id SKIP 2 PAGEBTITLE OFFcompute sum of line_item_total on order_idttitle left Order ID: v_order - right Order Date: v_o_date - skip 2spool logs/order_report_all_fail.txtselect /* OrdersChangeFail */ h.order_id ORDER_ID, order_date, li.line_item_id ID, li.product_name, p.supplier_product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_total from order_detail_header h, order_detail_line_items li, product_information p where h.order_id = li.order_id and li.product_id = p.product_id order by h.order_id, li.line_item_id ;spool offset lines 150480
  • 91. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEspool logs/OrdersChangeFail.log@pln.sql OrdersChangeFailPLAN_TABLE_OUTPUT-------------------------------------------------------------------------------------------SQL_ID avhuxuj0d23kc, child number 0-------------------------------------select /* OrdersChangeFail */ h.order_id ORDER_ID, order_date,li.line_item_id ID, li.product_name, p.supplier_product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_totalfrom order_detail_header h, order_detail_line_items li,product_information p where h.order_id = li.order_id andli.product_id = p.product_id order by h.order_id, li.line_item_idPlan hash value: 1984333101-------------------------------------------------------------------------------------------| Id |Operation |Name |Starts |E-Rows |A-Rows |Buffers |-------------------------------------------------------------------------------------------| 0 |SELECT STATEMENT | | 1 | | 417 | 45 || 1 | SORT ORDER BY | | 1 | 474 | 417 | 45 ||* 2 | HASH JOIN | | 1 | 474 | 417 | 45 || 3 | TABLE ACCESS FULL |PRODUCT_INFORMATION| 1 | 297 | 297 | 16 ||* 4 | HASH JOIN | | 1 | 474 | 417 | 29 || 5 | TABLE ACCESS FULL |PRODUCT_INFORMATION| 1 | 297 | 297 | 16 || 6 | NESTED LOOPS | | 1 | 474 | 417 | 13 || 7 | MERGE JOIN | | 1 | 474 | 417 | 9 ||* 8 | TABLE ACCESS BY INDEX RO|ORDERS | 1 | 79 | 79 | 2 || 9 | INDEX FULL SCAN |ORDER_PK | 1 | 114 | 114 | 1 ||* 10 | SORT JOIN | | 79 | 678 | 417 | 7 || 11 | TABLE ACCESS FULL |ORDER_ITEMS | 1 | 678 | 678 | 7 ||* 12 | INDEX UNIQUE SCAN |ORDER_STATUS_PK | 417 | 1 | 417 | 4 |-------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("PI"."PRODUCT_ID"="P"."PRODUCT_ID") 4 - access("OI"."PRODUCT_ID"="PI"."PRODUCT_ID") 8 - filter("O"."SALES_REP_ID" IS NOT NULL) 10 - access("O"."ORDER_ID"="OI"."ORDER_ID") filter("O"."ORDER_ID"="OI"."ORDER_ID") 12 - access("O"."ORDER_STATUS"="OS"."ORDER_STATUS")39 rows selected. 481
  • 92. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE Looking at this latest plan, the database is doing much more work after your changes, even thoughthe report is not taking any appreciable amount of extra time to complete. You know there is no goodreason for this to be so: you’ve only added one additional column to a table that was already the centralcomponent of the query. Furthermore, the table in question already required a full table scan, as mostof the columns are needed for the report. But the execution plan shows that your report is now doingtwo full table scans of the PRODUCT_INFORMATION table. Why? In this case, I’ve made a common error deliberately to illustrate how an execution plan can help findquality problems in changed code. Rather than simply add the new column to the existingORDER_DETAIL_LINE_ITEM view that is built on the PRODUCT_INFORMATION table, thePRODUCT_INFORMATION table has been joined to the ORDER_DETAIL_LINE_ITEM view, resulting ina second full table scan of the central table. This probably seems like a really foolish mistake to make, but it can be easily done. I’ve seen manydevelopers add a new column to a query by adding a new join to a table or view that was already part ofthe existing report. This error will have a clear and visible impact on an execution plan, especially if thequery is complex (and it usually is when this type of error is made). Listing 15-9 shows the executionplan for the same query once the additional join is removed and the column is added to the existingORDER_DETAIL_LINE_ITEM view instead.Listing 15-9. Order Report Execution Plan (Corrected)alter session set statistics_level = ALL;set linesize 115column order_id new_value v_order noprintcolumn order_date new_value v_o_date noprintcolumn ID format 99column order_total format 999,999,999.99BREAK ON order_id SKIP 2 PAGEBTITLE OFFcompute sum of line_item_total on order_idttitle left Order ID: v_order - right Order Date: v_o_date - skip 2spool logs/order_report_all_corrected.txtselect /* OrdersCorrected */ h.order_id ORDER_ID, order_date, li.line_item_id ID, li.product_name, li.supplier_product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_total from order_detail_header h, order_detail_line_items li where h.order_id = li.order_id order by h.order_id, li.line_item_id ;spool offset lines 150482
  • 93. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEspool logs/OrdersCorrected_plan.txt@pln.sql OrdersCorrectedPLAN_TABLE_OUTPUT--------------------------------------------------------------------------------------------SQL_ID 901nkw7f6fg4r, child number 0-------------------------------------select /* OrdersCorrected */ h.order_id ORDER_ID, order_date,li.line_item_id ID, li.product_name, li.supplier_product_id ITEM_NO, li.unit_price, li.discount_price, li.quantity, li.line_item_totalfrom order_detail_header h, order_detail_line_items li whereh.order_id = li.order_id order by h.order_id, li.line_item_idPlan hash value: 3662678147-------------------------------------------------------------------------------------------| Id |Operation |Name |Starts |E-Rows |A-Rows |Buffers |-------------------------------------------------------------------------------------------| 0 |SELECT STATEMENT | | 1| | 417 | 29 || 1 | SORT ORDER BY | | 1| 474| 417 | 29 ||* 2 | HASH JOIN | | 1| 474| 417 | 29 || 3 | TABLE ACCESS FULL |PRODUCT_INFORMATION| 1| 297| 297 | 16 || 4 | NESTED LOOPS | | 1| 474| 417 | 13 || 5 | MERGE JOIN | | 1| 474| 417 | 9 ||* 6 | TABLE ACCESS BY INDEX ROW|ORDERS | 1| 79| 79 | 2 || 7 | INDEX FULL SCAN |ORDER_PK | 1| 114| 114 | 1 ||* 8 | SORT JOIN | | 79| 678| 417 | 7 || 9 | TABLE ACCESS FULL |ORDER_ITEMS | 1| 678| 678 | 7 ||* 10 | INDEX UNIQUE SCAN |ORDER_STATUS_PK | 417| 1| 417 | 4 |-------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("OI"."PRODUCT_ID"="PI"."PRODUCT_ID") 6 - filter("O"."SALES_REP_ID" IS NOT NULL) 8 - access("O"."ORDER_ID"="OI"."ORDER_ID") filter("O"."ORDER_ID"="OI"."ORDER_ID") 10 - access("O"."ORDER_STATUS"="OS"."ORDER_STATUS")35 rows selected. You can see by this latest execution plan that your report is now performing as expected, with noadditional impact to performance or use of system resources. 483
  • 94. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEInstrumentationOne of my favorite Oracle features is instrumentation. The database itself is fully instrumented, which iswhy you can see exactly when the database is waiting and what it is waiting for. Without thisinstrumentation, a database would be something of a black box, providing little information aboutwhere resources are spending, or not spending, their time. Oracle also provides the DBMS_APPLICATION_INFO package that you can use to instrument thecode that you write. This package allows you to label the actions and modules within your code so thatyou can more easily identify which processes in your application are active. You can also combine yourinstrumentation data with Oracle’s Active Session History (ASH), Active Workload Repository (AWR),and other performance management tools to gain further insight into your application’s performancewhile easily filtering out other unrelated processes. The simplest method I know of for adding instrumentation to application code is the InstrumentationLibrary for Oracle (ILO), which is available at http://sourceforge.net/projects/ilo/. ILO is open sourcesoftware written and supported by my friends at Method-R. Method-R also offers the option to purchase alicense for ILO so that it can be used in commercial software products. I’ve been using ILO to instrumentcode for several years and have added functionality to the 2.3 version. The enhancements allow me torecord the exact start and stop time of an instrumented process using the database’s internal timereferences. This data can then be used to calculate statistical indicators on process execution times, whichhelps to highlight potential performance issues before they become major problems. I’ve also added code toenable 10044 tracing for a specific process by setting an On/Off switch in a table. So if I determine that Ineed trace data for a specific application process, I can set tracing to On for that process by its instrumentedprocess name and it will be traced every time it executes until tracing is set to Off again. The configurationmodule can also be used to set the elapsed time collection On or Off, but I usually prefer to leave elapsedtime recording on and purge older data when it is no longer useful. If you’d like to test the ILO instrumentation software as you go through the next few sections, startby downloading ILO 2.3 from SourceForge.net and install it per the instructions. You can then downloadthe code to store elapsed time and set the trace and timing configuration from the Apress download site.Instructions to add the updates are included in the ZIP file.Adding Instrumentation to CodeOnce you’ve installed the ILO schema, adding instrumentation to your application is easily done. There areseveral ways to accomplish this. Of course, you’ll need to determine the best method and the appropriateconfiguration based on your environment and requirements, but here are a few general guidelines: • Within your own session, you can turn timing and tracing on or off at any time. You can also instrument any of your SQL statements by executing the ILO call to begin a task before you execute your SQL statement and executing the call to end the task after the statement. This approach is shown in Listing 15-10. • You can encapsulate your code within a procedure and include the calls to ILO within the procedure itself. This has the added advantage of ensuring that every call to the procedure is instrumented and that the ILO action and module are labeled consistently. Consistent labeling will be very important if you want to aggregate your timing data in a meaningful way, or track trends in performance. I’ll look at the billing.credit_request procedure from Chapter 14 with added calls to ILO in Listing 15-11. • You can create an application-specific wrapper to call the ILO procedures. One benefit of using a wrapper is that you can make sure a failure in ILO does not result in a failure for the application process. While you do want good performance data, you don’t want to prevent the application from running because ILO isn’t working. A simple wrapper is included with the ILO update download at Apress.484
  • 95. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEListing 15-10. ILO Execution in a Single SessionSQL> exec ilo_timer.set_mark_all_tasks_interesting(TRUE,TRUE);PL/SQL procedure successfully completed.SQL> exec ilo_task.begin_task(Month-end,Purchasing);PL/SQL procedure successfully completed.SQL> @purchasing_reportSQL> exec ilo_task.end_task;PL/SQL procedure successfully completed. Selected from ILO_ELAPSED_TIME table: INSTANCE: TEST SPID: 21509 ILO_MODULE: Month-end ILO_ACTION: Purchasing START_TIME: 14-JUL-10 06.08.19.000000 AM END_TIME: 14-JUL-10 06.09.06.072642 AM ELAPSED_TIME: 46.42 ELAPSED_CPUTIME: .01 ERROR_NUM: 0Listing 15-11. Incorporating ILO into a Procedurecreate or replace procedure credit_request(p_customer_id IN NUMBER, p_amount IN NUMBER, p_authorization OUT NUMBER, p_status_code OUT NUMBER, p_status_message OUT VARCHAR2) IS /****************************************************************************** status_code values status_code status_message =========== =========================================================== 0 Success -20105 Customer ID must have a non-null value. -20110 Requested amount must have a non-null value. -20500 Credit Request Declined. ******************************************************************************/ v_authorization NUMBER; 485
  • 96. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEBEGIN ilo_task.begin_task(New Order, Credit Request); SAVEPOINT RequestCredit; IF ( (p_customer_id) IS NULL ) THEN RAISE_APPLICATION_ERROR(-20105, Customer ID must have a non-null value., TRUE); END IF; IF ( (p_amount) IS NULL ) THEN RAISE_APPLICATION_ERROR(-20110, Requested amount must have a non-null value., TRUE); END IF; v_authorization := round(dbms_random.value(p_customer_id, p_amount), 0); IF ( v_authorization between 324 and 342 ) THEN RAISE_APPLICATION_ERROR(-20500, Credit Request Declined., TRUE); END IF; p_authorization:= v_authorization; p_status_code:= 0; p_status_message:= NULL; ilo_task.end_task;EXCEPTION WHEN OTHERS THEN p_status_code:= SQLCODE; p_status_message:= SQLERRM; BEGIN ROLLBACK TO SAVEPOINT RequestCredit; EXCEPTION WHEN OTHERS THEN NULL; END; ilo_task.end_task(error_num => p_status_code);END credit_request;/Execution Script:set serveroutput onDECLARE P_CUSTOMER_ID NUMBER; P_AMOUNT NUMBER;486
  • 97. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE P_AUTHORIZATION NUMBER; P_STATUS_CODE NUMBER; P_STATUS_MESSAGE VARCHAR2(200);BEGIN P_CUSTOMER_ID := &customer; P_AMOUNT := &amount; billing.credit_request( P_CUSTOMER_ID => P_CUSTOMER_ID, P_AMOUNT => P_AMOUNT, P_AUTHORIZATION => P_AUTHORIZATION, P_STATUS_CODE => P_STATUS_CODE, P_STATUS_MESSAGE => P_STATUS_MESSAGE );commit; DBMS_OUTPUT.PUT_LINE(P_CUSTOMER_ID = || P_CUSTOMER_ID); DBMS_OUTPUT.PUT_LINE(P_AMOUNT = || P_AMOUNT); DBMS_OUTPUT.PUT_LINE(P_AUTHORIZATION = || P_AUTHORIZATION); DBMS_OUTPUT.PUT_LINE(P_STATUS_CODE = || P_STATUS_CODE); DBMS_OUTPUT.PUT_LINE(P_STATUS_MESSAGE = || P_STATUS_MESSAGE);END;/Execution:SQL> @exec_CreditRequestEnter value for customer: 237Enter value for amount: 10000P_CUSTOMER_ID = 237P_AMOUNT = 10000P_AUTHORIZATION = 8302P_STATUS_CODE = 0P_STATUS_MESSAGE =PL/SQL procedure successfully completed.SQL> @exec_CreditRequestEnter value for customer: 334Enter value for amount: 500P_CUSTOMER_ID = 237P_AMOUNT = 500P_AUTHORIZATION = 487
  • 98. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEP_STATUS_CODE = -20500P_STATUS_MESSAGE = ORA-20500: Credit Request Declined.PL/SQL procedure successfully completed. Selected from ILO_ELAPSED_TIME table: INSTANCE: TEST SPID: 3896 ILO_MODULE: New Order ILO_ACTION: Request Credit START_TIME: 14-JUL-10 01.43.41.000000 AM END_TIME: 14-JUL-10 01.43.41.587155 AM ELAPSED_TIME: .01 ELAPSED_CPUTIME: 0 ERROR_NUM: 0 The level of granularity you decide to implement with your instrumentation depends on your goals.For some tasks, it will be perfectly acceptable to include multiple processes in a single ILO module oraction. For critical code, I recommend that you instrument the individual processes with their ownaction and module values, which will give you more visibility into complex procedures. If you aresupporting an application that is not instrumented and it seems like too big a task to go back andinstrument all the existing code, consider adding the instrumentation just to the key processes. Again, how you decide to implement will depend on your needs. Instrumentation is exceptionallyuseful for testing code and configuration changes during development and performance testing. Oncethe calls to ILO have been built into the code, you can turn timing/tracing on or off in production toprovide definitive performance data. Overhead is exceedingly low and being able to enable tracingeasily will help you find the problems much more quickly. Using the ILO_ELAPSED_TIME table to store performance data will typically allow you to retaincritical performance data for longer periods of time. While it is possible to set longer retention values forAWR data, some sites may not have the resources available to keep as much data as they would like.Since the ILO data is not part of the Oracle product itself, you have the option to customize the retentionlevels to your needs without endangering any Oracle delivered capabilities.■NOTE Keep the ILO code in its own schema and allow other schemas to use the same code base. This willkeep the instrumentation code and data consistent, which will allow you to roll performance data up to the serverlevel or across other multiple servers when appropriate.Testing for PerformanceOnce you’ve added instrumentation to your code, you open the door to all kinds of potential uses for theinstrumentation and the data you collect. Earlier in this chapter, I talked about building test harnessesby automating many small unit test scripts and then replaying those tasks to confirm that new and oldfunctionality are working as expected and that old bugs have not been reintroduced. If your code isinstrumented, you can record the timing for each execution of the test harness and you will have488
  • 99. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEcomplete information on the exact amount of elapsed time and CPU time required for each labeledmodule and action. The ILO package includes an ILO_COMMENT field in addition to the ILO_MODULE andILO_ACTION labels. In some cases, this field can be used to record some identifying piece ofinformation about a specific process execution. For example, if you were to add instrumentation to theorder transaction from the last chapter, you could record the order number in the ILO_COMMENT field.Then if you found an exceptionally long execution in your ILO_ELAPSED_TIME table, you could connectthat execution time with an order number, which then connects you to a specific customer and a list ofordered items. Combining this information with the very specific timestamp recorded in your table canhelp you troubleshoot the problem, ensure the transaction did process correctly, and determine thecause of the unusually long execution time. In other cases, you may want to use the comment field to label specific set of test results for futurereference. When testing changes to an application or instance configuration, it’s always better to makeone change and measure the results before making additional adjustments. Otherwise, how will youknow which change was responsible for the results you obtained? This can be very difficult to do, unlessyou’ve created a test harness and measurement tool that can be easily and consistently re-executedmultiple times. By making a single change, re-executing the complete test package while recordingtiming data, and labeling the results set of that test execution, you create a series of data sets, eachshowing the impact of a specific change, test dataset, or stress factor. Over time, this information can beused to evaluate the applications ability to perform under a wide range of conditions. A sample of data retained from one such test harness is shown in Table 15-1 (times are shown inseconds).Table 15-1. Repetitive Test Results CPU CPU CPU CPU ILO ACTION COUNT MIN AVG MAX VAR MIN AVG MAX VAR process 1 46 0 .01 .09 0 0 .008 .03 0 process 2 2 .12 .125 .13 0 .12 .125 .13 0 process 3 2772526 0 .382 4.44 .078 0 .379 2.6 .074 child 3a 2545208 .01 .335 2.26 .058 .01 .332 1.77 .055 child 3b 2752208 0 .065 2.24 .011 0 .065 1.39 .01 child 3c 2153988 0 0 .21 0 0 0 .02 0 child 3d 2153988 0 0 .36 0 0 0 .07 0 child 3e 2153988 0 0 .16 0 0 0 .02 0 child 3f 2153988 0 0 .42 0 0 0 .02 0 process 4 1564247 0 .001 .18 0 0 .001 .02 0 process 5 2873236 0 .043 6.2 .013 0 .041 .49 .006 process 6 149589 0 .018 5.53 .002 0 .013 .11 0 process 7 2395999 0 .001 6 0 0 .001 .03 0 489
  • 100. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE While the numbers shown above aren’t particularly meaningful on their own, if you have this set ofnumbers representing code executions prior to a change and you have another set of numbers from thesame server with the same data set representing code execution after the code has been changed, youhave definitive information regarding the impact your code changes have had on the database. Imaginebeing able to quickly and painlessly repeat this test for subsequent code changes and configurationadjustments, and you’ll begin to appreciate the potential of code instrumentation combined withrepeatable, automated test processes.Testing to DestructionTesting a system to its breaking point can be one of the more entertaining aspects of software testing,and meetings to brainstorm all the possible ways to break the database are seldom dull. Early in mycareer, I developed and managed an Oracle database application built using client/server technology.(Yes, this was long ago and far away.) The application itself was a problem tracking tool that allowedmanufacturing workers to record issues they found and send those problems to Engineering for reviewand correction. The initial report landed in Quality Engineering, where it would be investigated andassigned to the appropriate Engineering group. As each Engineering department signed off on theirwork, the request would move on to the next group. The application was reasonably successful so itended up on many workstations through a very large facility. If you ever want to see “testing to destruction” in action, try supporting a database applicationinstalled on the workstations of hundreds of electrical, hydraulic, and structural engineers. In a fairlyshort period of time, I learned that engineers will do everything in their power to learn about thecomputers on their desks, and they considered breaking those computers and the applications on themto be an educational experience. I can’t say that I disagree with them: sometimes taking something apartjust so you can build it again really is the best way to understand the guts of the tool. However, after several months of trying to support this very inquisitive group of people, I developeda new approach to discourage excessive tampering. By keeping a library of ghosted drives containingthe standard workstation configuration with all the approved applications, I could replace the hard driveon a malfunctioning computer in under 10 minutes and the engineer and I could both get back to work.Since everyone was expected to store their work on the server, no one could really object to my repairmethod. However, most engineers did not like losing their customized desktops, so they soon quit tryingquite so hard to break things. Although I loved to grumble at those engineers, I really owe them a very big thank you, for nowwhenever I need to think about how to test a server or application to destruction, all I need to do is thinkabout those engineers and wonder what they would do. And never discount even the craziest ideas: ifyou can think of it, someone is likely to try it. As you work to identify your system’s weak links, considereverything on the following list, and then think of some more items: Data Entry: What happens when a user or program interface sends the wrong kind of data or too much data? Task Sequences: What happens when a user skips a step or performs the tasks out of order? Repeating/Simultaneous Executions: Can the user run the same process simultaneously? Will that action corrupt data or will it just slow the process down? Unbounded Data Ranges: Can the user request an unreasonable amount of data? What happens if the user enters an end range that is prior to the start range (such as requesting a report on sales from July 1, 2010 to June 30, 2010)? Resource usage: Excessive use of CPU, memory, temporary storage and undo space can impact many users at the same time. Your DBA should limit usage with resource caps appropriately, but you still need to identify all the potential ways users and processes can grab more than their fair share.490
  • 101. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCE I bet some of you could add some very interesting options for other ways to break systems. Can youalso identify the ways to prevent those problems? While finding the best correction is a bit harder andnot as entertaining, every time you can make it difficult for a user to break your code, you create a morerobust system—one that will need less support and less maintenance over the long run. Every system will have its own weakest links. Once you’ve identified those weaknesses, assembleyour unit tests into a test harness that will push that resource beyond its limits so you can see how thesystem responds. In general, it seems that memory and I/O usage are the primary stressors for adatabases system. However, lately I’ve been working on an Oracle 11g database with spatialfunctionality, and in this case, CPU processing is the system’s bottleneck. When we designed the systemcapacity tests, we made certain that the spatial processes would be tested to the extreme and wemeasured the internal database performance using the ILO data as shown in the last section. We alsohad external measurements of the total application and system performance, but having the ILO elapsedtime data provided some unique advantages over other test projects I’ve participated in. First and foremost, the ILO data provides specific measurements of the time spent in the database.This makes it easier to troubleshoot performance issue that do show up, as you can quickly tell when theprocess is slow in the database and when it is not. A second advantage is that the recorded timestampsgive a very specific indicator of exactly when a problem occurred, what other processes were running atthe same time, and the specific sequencing of the application processes. With this information, you caneasily identify the point when the system will hit the knee in its performance curve. And since theelapsed time module in ILO uses DBMS_UTILITY.get_time and DBMS_UTLITITY.get_cpu_time, you canrecord exactly how much time your process spent active in the database and what portion of that timewas spent on CPU. This detailed performance data is also useful for troubleshooting, as the low level timestamps assistin narrowing down the timeframe for the problem. Once you know the specific timeframe you need toresearch, you can review a much smaller quantity of AWR or StatsPack data to see what happened andfind the answers quickly. Once the window is small enough, any problem will be almost immediatelyvisible. I’ll look at a specific case in the next section.Troubleshooting through InstrumentationSometimes it can be difficult to identify the cause of small problems. When you don’t know the source ofthe problem, you also don’t know the potential impact the problem could have on your application. Inone such case, developers had noticed timeouts from the database at random intervals, yet the processthey suspected of causing the issue showed no sign of the errors and the database appeared to beworking well below its potential. About a week after a new test server was installed, a review of the ILO_ELAPSED_TIME table showedthat most tasks were performing well, except there were two processes that had overrun the 30 secondtimeout clock on the application. The error numbers recorded on the tasks showed the front endapplication had ended the connection: this message was consistent with a possible timeout, but it wasnot very helpful. The captured ILO data is shown in Table 15-2. If you take a look at process 7, you will note that the maximum completion time does exceed 30seconds and the variance in processing times is relatively high when compared to other processes in theapplication. The process spends almost no time on CPU, so this is a problem worth investigating. Whereis this time going? It’s also interesting to note that this was not a process that anyone would haveexpected to have a performance issue. Process 3 had been the target of previous timeout investigations;it has to perform considerably more work than process 7. 491
  • 102. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCETable 15-2. Timeout Errors CPU CPU CPU CPU ILO ACTION COUNT MIN AVG MAX VAR MIN AVG MAX VAR process 1 4 0.01 0.015 0.03 0 0 0.01 0.03 0 process 2 2 0 0 0 0 0 0 0 0 process 3 56 0.01 0.112 0.8 0.015 0.01 0.109 0.62 0.011 child 3a 36 0.04 0.078 0.15 0 0.03 0.078 0.15 0.001 child 3b 56 0 0.01 0.09 0 0 0.009 0.07 0 child 3c 36 0 0 0.01 0 0 0.001 0.01 0 child 3d 36 0 0.001 0.01 0 0 0 0.01 0 child 3e 36 0 0.001 0.01 0 0 0.001 0.01 0 child 3f 36 0 0.001 0.01 0 0 0.001 0.01 0 process 4 8 0 0.01 0.02 0 0 0.008 0.02 0 process 5 1 0.01 0.01 0.01 0 0.01 0.01 0.01 0 process 6 152 0 0.002 0.1 0 0 0.002 0.09 0 process 7 90 0 0.681 30.57 20.449 0 0.002 0.02 0 process 8 1 0 0 0 0 0.01 0.01 0.01 0 process 9 77 0 0.001 0.01 0 0 0.001 0.01 0 process 10 8 0 0.008 0.01 0 0 0.008 0.01 0 Next, let’s take a look at Table 15-3, which contains the results of a query looking for all cases inwhich process 7 exceeded 30 seconds.492
  • 103. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCETable 15-3. Processes Exceeding 30 Seconds SPID ILO ACTION START TIME END TIME ELAPSED TIME ERROR 22-JUL-10 22-JUL-10 28959 process 7 05.40.00.000000 PM 09.40.31.234635 PM 30.45 –1013 22-JUL-10 22-JUL-10 29221 process 7 05.55.30.000000 PM 09.56.00.619850 PM 30.57 –1013 The start and stop times shown in Table 15-3 reflect the connection pool start and stop times, whichis a much wider window than you need in order to troubleshoot this problem. You also record internaldatabase and CPU clock times in the ILO_ELAPSED_TIME table: it is these values that are used tocalculate the elapsed times as shown in Table 15-4. Table 15-4 also shows the sequential execution ofthe processes, and you’ll notice that process 7 was executed repeatedly within intervals of just a fewseconds.Table 15-4. Sequential Listing of Processes with Internal Clock Times SPID ILO ACTION GO TIME STOP TIME ELAPSED TIME CPU TIME ERROR 29221 process 7 498854690 498854690 0 0 0 28959 process 7 498856045 498859090 30.45 0 -1013 29047 process 7 498862109 498862109 0 0 0 29309 process 3 498862111 498862121 0.1 0.11 0 29309 child 3a 498862113 498862121 0.08 0.07 0 29309 child 3b 498862113 498862113 0 0 0 29309 child 3c 498862121 498862121 0 0 0 29309 child 3d 498862121 498862121 0 0 0 29309 child 3e 498862121 498862121 0 0 0 29309 child 3f 498862121 498862121 0 0 0 28959 process 7 498947571 498947571 0 0 0 29221 process 7 498948957 498952014 30.57 0 -1013 continued 493
  • 104. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCETable 15-4. Sequential Listing of Processes with Internal Clock Times SPID ILO ACTION GO TIME STOP TIME ELAPSED TIME CPU TIME ERROR 29047 process 7 498957717 498957717 0 0 0 29309 process 3 498957718 498957728 0.1 0.1 0 29309 assign_child1 498957720 498957728 0.08 0.07 0 29309 assign_child2 498957720 498957720 0 0 0 29309 assign_child3 498957728 498957728 0 0 0 29309 assign_child4 498957728 498957728 0 0.01 0 29309 assign_child5 498957728 498957728 0 0 0 29309 assign_child6 498957728 498957728 0 0 0 Looking at the two processes that exceeded thirty seconds, you have a very small timeframe whenboth errors occurred. Your next step will be to check the Active Workload Repository (AWR) for thatparticular timeframe. Reviewing the AWR data shown in Listing 15-12, the problem is immediately clear.Listing 15-12. AWR Output for One Hour TimeframeTop 5 Timed Foreground Events~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Avg wait % DBEvent Waits Time(s) (ms) time Wait Class------------------------------ ------------ ----------- ------ ------ ----------enq: TX - row lock contention 2 61 30511 78.6 ApplicationDB CPU 12 15.0SQL*Net break/reset to client 21,382 5 0 6.6 Applicationlog file sync 32 0 1 .1 CommitSQL*Net message to client 10,836 0 0 .0 Network Between the series of events shown in Table 15-2 and the AWR output shown in Listing 15-20, thecause of the timeouts becomes clear. Process 7 had been called two or even three times, when only oneexecution should be necessary. If those calls came in fast enough, the second process would attempt toupdate the same row, creating a lock and preventing the first process from committing. When process 1could not commit in 30 seconds, the process would terminate and the second (or third) process wouldbe able to save its changes successfully. Since the application has a built-in timeout, this problem is aminor one, and a self correcting one at that. The tables above show data from a newly installed server with only a few executions. I’ve selectedthis particular data set as it is easy to use as an example, but it does make it appear as if it would havebeen possible to spot this problem with almost any other troubleshooting tool. However, consider this:494
  • 105. CHAPTER 15 ■ TESTING AND QUALITY ASSURANCEwhen this same data is reviewed on more active test servers over longer periods of time, timeouts for thisprocess may occur on one day in any given month, and there are likely to be no more the four to sixprocesses that exceed 30 seconds on that day. This process may execute hundreds of thousands of timesover two or three months on a busy test server. And then there are test results like those shown in Table15-1. In that case, the process is executed millions of times without a single timeout. Trying to spot thisproblem from an AWR report and then identifying the process that caused the application lock wouldtake a bit more time with that many executions. And while this problem is not significant right now, ithas the potential to cause the application to miss required performance targets. Due to the datarecorded by the instrumentation, the problem can be monitored and addressed before that happens. Although this is a simple example, identifying these kinds of problems can be difficult, especiallyduring typical development test cycles. Early in unit testing, tests are not normally executed in rapidsuccession, so some problems may not appear until later. And once testing has moved on to loadtesting, an occasionally longer running process or two may not be noticed among millions of executions.Yet by using the ILO execution times to abbreviate the amount of AWR performance data that must bereviewed, problems like this can be identified and diagnosed in just a few moments. And while accessto AWR and ASH data may not be available to you in all development environments, the instrumentationdata you create will be.SummaryI’ve covered a wide range of information in this chapter, including execution plans and instrumentation,performance and failures, testing theory and practical application. Each of these topics could have beena chapter or even an entire book on their own, which is why there are already many, many books outthere. What I hope you will take away from this chapter is the recognition that each system has its ownstrengths and limitations, so any testing and measurement approach should be customized to someextent for the specific system needs and performance requirements. No single testing method can beperfectly effective for all systems, but the basic approach is fairly straightforward. Break the work downinto measurable test modules, measure, adjust. and measure again. Whenever possible, minimize thechanges between test iterations but keep the test realistic. You can test the functionality of your codewith unit tests on a subset of the data, but testing performance requires a comparable amount of data ona comparably configured system. Verifying that a report runs exceptionally fast on a development serverwith little data and no other users doesn’t prove anything if that report will be run on a multiuser datawarehouse. Understanding what you need to measure and confirm is crucial to preparing anappropriate test plan. And be sure to consider testing and performance early in the process. That doesnot necessarily mean that you need to write a perfectly optimized piece of code right out of the gate, butyou should be aware of the limitations your code is likely to face in production and write the codeaccordingly. It also doesn’t hurt to have a few alternatives in your back pocket, so you are prepared tooptimize the code and measure it once again. 495
  • 106. ! ! ! ! !! !! ! ! ! !
  • 107. ! ! !!!! ! ! ! ! ! ! ! ! ! !