Avoid Data type Mismatch..................................................................................... 2
Avoid Functions on Indexed Columns.....................................................................2 Defne Initial Columns in Composite Indexes.........................................................2 Use WHEE Instead o! HA"I#$.............................................................................. 2 Avoid #ested %ue&ies............................................................................................ ' Usin( D&ivin( )a*le in U+E ,ased -ptimi.e&........................................................' /#ot exists/ and -ute& 0oins.................................................................................... ' Avoid #-) E%UA+.................................................................................................. ' Use Function ,ased Index !o& #"+ Columns...........................................................' educe the #um*e& o! )&ips to the Data*ase........................................................' Use )U#CA)E Instead o! DE+E)E.........................................................................1 Use DEC-DE.......................................................................................................... 1 Use Count234 to Count o5s !&om )a*le.................................................................6 Use U#I-#7A++ Instead o! U#I-# 2Whe&e 8ossi*le4...............................................6 Use WHEE Instead o! -DE ,9 Clause..............................................................: Use I# Instead o! -.............................................................................................. : Use Full )a*le ;cans............................................................................................... < When to (o !o& Fast Full ;cans............................................................................... < ,itmap Indexes...................................................................................................... < Usin( composite indexes....................................................................................... < C&eate Indexes on Fo&ei(n =ey..............................................................................< Avoid Unnecessa&y Data*ase Calls........................................................................< Use o! 8+;>I#)E$E.............................................................................................. ? Avoid ,I#A9>I#)E$E.......................................................................................... ? 8innin( ;to&ed 8&ocedu&es..................................................................................... ? Use WHE# Clause in )&i((e&s................................................................................. ? Use AF)E o5 )&i((e&s........................................................................................ ? Use ,ul@ ,indin(.................................................................................................... ? Use +IMI) clause.................................................................................................... ? )a@in( Advanta(e o! 8a&tition 8&unin(.................................................................AA 8-3 C )unin( $uidelines.................................................................................... A2 Avoid Data type Mismatch ------------------------ Avoid data type mismatch for index columns. If there are datatype mismatches then the index on that particular column will not be used and a FULL TABLE !A" will be made. Example# $rder%"umber is a number column in $E%$&'E&%'ETAIL%F table. But in the followin(# ELE!T description F&$) oe%order%details%f *+E&E order%number,-../.01- The where clause will be executed as to%char2order%number3 , 4../.01- Avoid Functions on Indexed Columns ---------------------------------- Avoid functions on Index columns. In this case too5 the presence of a function will ma6e the optimi7er (o for a FULL TABLE !A". Example# If chedule%date is indexed in $E%$&'E&%'ETAIL%F table the where clause To%char2schedule%date5-dd8mon-yyyy-3 , 49.8:an8099;- will prevent the usa(e of the index. Defne Initial Columns in Composite Indexes ------------------------------------------ *hen usin( a composite index5 ensure that the initial columns are defined. If the initial columns are not used5 the composite index will not be made use of. Example# !onsider a table in which brand and product columns have a composite index. And we execute the followin( <uery. elect count2=3 From products *here price > .999? The composite index will not be made use of. But the same composite index will be hit for the <uery (iven below# elect count2=3 From products *here brand , 4Arrow-? It-s important to ensure that the initial columns are defined while ma6in( use of composite indexes. The same index can be hit by usin( the followin( code# elect count2=3 From products *here brand @ 49- and price > .999? Use WHERE Instead of HAI!" -------------------------- It-s more efficient to use where clause instead of havin( clause. Example# !onsider this <uery elect brand5 sum2price3 From products Aroup by brand +avin( brand , 4Arrow-? The above <uery can be re8written as shown below. This will ensure that the index5 if present5 is made use of. elect brand5 sum2price3 From products *here brand , 4Arrow- Aroup by brand? Avoid !ested #ue$ies -------------------- "ested <ueries need to be rewritten usin( Boins5 whenever possible5 for efficiency. Usin% D$ivin% &a'le in RU(E )ased *ptimi+e$ ------------------------------------------ Ensure that the smallest table appears last when specifyin( a Boin <uery if you are usin( a &ULE based optimi7er. ,!ot exists, and *ute$ -oins ---------------------------- &eplace Cnot inD by Cnot existsD or Couter BoinD. This will ensure that indexes5 if present5 are hit. Avoid !*& E#UA( -------------- &eplace EF,E by EunionE or E>E and E@E Use Function )ased Index fo$ !( Columns ---------------------------------------- )a6e use of Function Based indexes in case "GL has to be avoided. Example# !reate index idx%test on test2nvl2column%.5933? Reduce the !um'e$ of &$ips to the Data'ase ------------------------------------------ Every time an HL statement is executed5 $&A!LE needs to perform some internal processin(5 namely5 the statement needs to be parsed5 indexes evaluated5 variables bound and data bloc6s read. The more you can reduce the number of database accesses5 the more overheads you can save. Example# There are ; distinct ways of retrievin( data about employees who have employee numbers 9;I0 or 90J.. )ethod . 2Least Efficient3# ELE!T E)K%"A)E5 ALA&L5 A&A'E F&$) E)K *+E&E E)K%"$ , 9;I0? ELE!T E)K%"A)E5 ALA&L5 A&A'E F&$) E)K *+E&E E)K%"$ , 90J.? )ethod 0 2"ext )ost Efficient3# 'E!LA&E !U&$& !.2E%"$ "U)BE&3 I ELE!T E)K%"A)E5 ALA&L5 A&A'E F&$) E)K *+E&E E)K%"$ , E%"$? BEAI" $KE" !.2;I03? FET!+ !. I"T$ M5 M5 M? . . $KE" !.20J.3? FET!+ !. I"T$ M5 M5 M? !L$E !.? E"'? )ethod ; 2)ost Efficient3# ELE!T A.E)K%"A)E5 A.ALA&L5 A.A&A'E5 B.E)K%"A)E5 B.ALA&L5 B.A&A'E5 F&$) E)K A5 E)K B *+E&E A.E)K%"$ , 9;I0 A"' B.E)K%"$ , 90J.? It-s advisable to ma6e use of tored Krocedures wherever possible. Use &RU!CA&E Instead of DE(E&E ------------------------------ *hen rows are removed from a table5 usin( 'ELETE5 the rollbac6 se(ments are used to hold undo information. If you do not commit your transaction and re<uire the deleted rows5 $racle restores the data to the state it was in before your transaction started from these rollbac6 se(ments. *ith T&U"!ATE5 no undo information is (enerated. $nce the table is truncated5 the data cannot be recovered 2no rollbac6 is possible3. +ence is faster and needs fewer resources. Use T&U"!ATE rather than 'ELETE for deletin( rows of small or lar(e tables when you are sure you do not need the undo information. Use DEC*DE ---------- The 'E!$'E statement provides a way to avoid havin( to scan the same rows repetitively or to Boin the same table repetitively.
imilarly5 'E!$'E can be used in A&$UK BL or $&'E& BL clause effectively. In $racle Qi and above !AE statement can also be used instead of 'E!$'E 8 its more readable and flexible. Example# ELE!T case when instr2UKKE&2nvl2approver5E!hira(E335E!+I&AAE3 @ 9 then E!hira(E when instr2UKKE&2nvl2approver5E!hira(E335E+A&)ILAE3 @ 9 then EharmilaE when instr2UKKE&2nvl2approver5E!hira(E335E"AAA&A:A"E3 @ 9 then E"a(araBanE when instr2UKKE&2nvl2approver5E!hira(E335E"AAA&A":A"E3 @ 9 then E"a(araBanE else approver end5 count2=3 "o%$f%Katches F&$) apps.patch%format where substr2to%char2!&EATI$"%'ATE5Edd8mon8yyyyE35I5Q3, substr2to%char2trunc2sysdate35Edd8mon8yyyyE35I5Q3 (roup by 88FI!AL%*EEN5 case when instr2UKKE&2nvl2approver5E!hira(E335E!+I&AAE3 @ 9 then E!hira(E when instr2UKKE&2nvl2approver5E!hira(E335E+A&)ILAE3 @ 9 then EharmilaE when instr2UKKE&2nvl2approver5E!hira(E335E"AAA&A:A"E3 @ 9 then E"a(araBanE when instr2UKKE&2nvl2approver5E!hira(E335E"AAA&A":A"E3 @ 9 then E"a(araBanE else approver end 88order by fiscal%wee6 R Use Count./0 to Count Ro1s f$om &a'le ------------------------------------ !ontrary to popular belief5 !$U"T2=3 is faster than !$U"T2.3. If the rows are bein( returned via an index5 countin( the indexed column is faster still. Example# elect !$U"T2E)K"$3 from emp? Use U!I*!2A(( Instead of U!I*! .Whe$e 3ossi'le0 ---------------------------------------------- *hen the <uery performs a U"I$" of the results from two <ueries5 the result sets are mer(ed via the U"I$"8ALL operation5 and then it is processed by a $&T U"IHUE operation before the records are returned to the user.
If the <uery had used a U"I$"8ALL function in place of U"I$"5 then the $&T U"IHUE operation would not have been necessary5 thus improvin( the performance of the <uery.
)ost Efficient # ELE!T A!!T%"U)5 BALA"!E%A)T F&$) 'EBIT%T&A"A!TI$" *+E&E T&A"%'ATE , 4;.8'E!8J/- U"I$" ALL ELE!T A!!T%"U)5 BALA"!E%A)T F&$) !&E'IT%T&A"A!TI$" *+E&E T&A"%'ATE , 4;.8'E!8J/- Use WHERE Instead of *RDER )4 Clause ------------------------------------ $&'E& BL clauses use an index only if they meet two re<uirements.
S All the columns that ma6e up the $&'E& BL clause must be contained within a sin(le index in the same se<uence. S All the columns that ma6e up the $&'E& BL clause must be defined as "$T "ULL within the table definition. &emember5 null values are not contained within an index.
*+E&E clause indexes and $&'E& BL indexes cannot be used in parallel.
"$" U"IHUE I"'EP 2'EKT%TLKE3 Least Efficient# 2+ere5 index will not be used3
ELE!T 'EKT%!$'E F&$) 'EKT $&'E& BL 'EKT%TLKE
Explain Klan#
$&T $&'E& BL TABLE A!!E FULL
)ost Efficient# 2+ere5 index will be used3
ELE!T 'EKT%!$'E F&$) 'EKT *+E&E 'EKT%TLKE @ 9
Explain Klan#
TABLE A!!E BL &$*I' $" E)K I"'EP &A"AE !A" $" 'EKT%I'P Use I! Instead of *R -------------------- The followin( <uery can be replaced usin( I" to improve the performance# Least Efficient# ELE!T . . . F&$) L$!ATI$" *+E&E L$!%I' , .9 $& L$!%I' , 09 $& L$!%I' , ;9 )ost Efficient# ELE!T . . . F&$) L$!ATI$" *+E&E L$!%I" I" 2.95095;93 Use Full &a'le 5cans -------------------- *hen index scan performs more bloc6 visitations than a full table scan5 better to use full table scans When to %o fo$ Fast Full 5cans ------------------------------ Index Fast full scans are an alternative to full table scans when the index contains all the columns that are needed for the <uery. This can be used by usin( $ptimi7er +int I"'EP%FF. )itmap Indexes -------------- !onsider bitmap indexes when where clause predicate contain low8cardinality columns5 contain lo(ical operations such as $&5 A"' or "$T on those columns. It is advisable that bitmap indexes are not used in $LTK applications. Usin% composite indexes ---------------------- )a6e use of composite indexes. These need to be ordered in the decreasin( order of selectivity. C$eate Indexes on Fo$ei%n 6ey ---------------------------- !reate indexes on forei(n 6ey columns if the <ueries always retrieve master8detail relationship8based rows.
PL/SQL Tuning Guidelines ------------------------ Use Bind Variables ------------------ )a6in( use of bind variables will reduce fre<uent parsin(. Avoid Unnecessa$y Data'ase Calls -------------------------------- Avoid elects statements a(ainst the database when the same functionality can be achieved in KLRHL by Bust assi(nin( to the variables. ystem variables li6e UI'5 L'ATE can be assi(ned to variables without elect statements. *e can ma6e use of assi(nments instead of ma6in( an HL statement. Example# 'eclare From%date date? be(in elect sysdate into from%date from dual? End? !an be replaced by 'eclare From%date be(in From%date#,sysdate End? Use of 3(57I!&E"ER ------------------ )a6e use of KL%I"TEAE& instead of "U)BE& or I"TEAE& in loop variables as KL%I"TEAE& ma6es use of machine arithmetic whereas "U)BE& and I"TEAE& ma6es use of functional arithmetic. +ence KL%I"TEAE& is faster. Avoid )I!AR47I!&E"ER -------------------- The use of BI"A&L%I"TEAE& datatypes within arithmetic operations ma6es it slower than the same operation usin( an I"TEAE& datatype. 3innin% 5to$ed 3$ocedu$es ------------------------ Anonymous KLRHL should be moved into a stored obBect when possible and this obBect should then be pinned in the shared pool usin( dbms%shared%pool.6eep23 if the obBect is fre<uently referenced. Use WHE! Clause in &$i%%e$s -------------------------- Use a *+E" clause on the tri((er if possible so that the tri((er is fired only when absolutely necessary. Use AF&ER Ro1 &$i%%e$s ---------------------- Use AFTE& row tri((ers instead of BEF$&E row tri((ers5 wherever possible5 as AFTE& row tri((ers are faster. Use )ul8 )indin% ---------------- Bul6 binds improve performance by minimi7in( the number of context switches between KLRHL and HL en(ines while they pass an entire collection of elements 2varray5 nested tables5 index8by table5 or host array3 as bind variables bac6 and forth. )a6e use of BULN !$LLE!T and F$&ALL. *hen there is a lar(er data volume and you need to fetch data for some validations andRor processin(5 it is (enerally better 2performance8wise3 to use the BULN constructs. Use (IMI& clause ---------------- Usin( LI)IT clause durin( BULN !$LLE!T will reduce !KU utili7ation. Example# set serveroutput on declare TLKE tstrin(s I TABLE $F strin(20//3 I"'EP BL BI"A&L%I"TEAE&? type tnumbers I TABLE $F FL$AT I"'EP BL BI"A&L%I"TEAE&? n tstrin(s? cursor c is select obBect%name from user%obBects? bul6%limit number? be(in open c? 88 first bul6 .9 dbms%output.put%line2E88 first bul6 .9E3? bul6%limit #, .9? fetch c bul6 collect into n LI)IT bul6%limit? for i in n.first..n.last loop dbms%output.put%line2n2i33? end loop? 88 second bul6 ./ dbms%output.put%line2E88 second bul6 ./E3? bul6%limit #, ./? fetch c bul6 collect into n LI)IT bul6%limit? for i in n.first..n.last loop dbms%output.put%line2n2i33? end loop? close c? end? R More Examples of Bulk Binding ------------------------------ !U&$& dis%cust%customer%id%cur I ELE!T R=T $&'E&E' UE%"L2dm dc3 I"'EP2dc $%'I!$U"T%!UT$)E&%";3 I"'EP2dm HK%'I!$U"T%)AKKI"A%".3 =R dm.new%list%header%id5 dc.customer%id5 88dc.site%use%id5 88dc.customer%class%code5 dc.context5 dc.start%date%active5 dc.end%date%active F&$) 2 select distinct old%discount%id5 new%list%header%id from <p%discount%mappin(3 dm5 so%discount%customers dc *+E&E dm.old%discount%id , dc.discount%id A"' dc.customer%id is not null? L$$K "E*%LIT%+EA'E&%I'%T.'ELETE? !UT$)E&%I'%T.'ELETE? ITE%UE%I'%T.'ELETE? !UT$)E&%!LA%!$'E%T.'ELETE? !$"TEPT%T.'ELETE? TA&T%'ATE%A!TIGE%T.'ELETE? E"'%'ATE%A!TIGE%T.'ELETE? FET!+ dis%cust%customer%id%cur BULN !$LLE!T I"T$ "E*%LIT%+EA'E&%I'%T5 !UT$)E&%I'%T5 88ITE%UE%I'%T5 88!UT$)E&%!LA%!$'E%T5 !$"TEPT%T5 TA&T%'ATE%A!TIGE%T5 E"'%'ATE%A!TIGE%T? LI)IT .999? 888 Fetch .999 records at a time BEAI" IF new%list%header%id%t.FI&T is not null then
E"' IF? EPIT *+E" dis%cust%customer%id%curO"$TF$U"'? EP!EKTI$" *+E" GALUE%E&&$& T+E" null? *+E" I"GALI'%"U)BE& T+E" null? *+E" $T+E& T+E" v%errortext #, UBT&2HLE&&)5 .50I93? 88oe%debu(.add2EIn others of dis%customers%cur%customer%idE3? N #, s<lOrowcount T new%list%header%id%t.first? &$LLBA!N? <p%util.lo(%error2new%list%header%id%t2N35"ULL5 "ULL5 "ULL5 "ULL5 "ULL5 "ULL5"ULL5 EHK%HUALIFIE&E5 v%errortext5 EUK'ATE%HUALIFIE&E3? &AIE? E"'? commit? E"' L$$K? Error !andling in Bulk Binds ---------------------------- Avoid usin( commits after each record 8 this can hamper your code-s performance. The Bul6 !ollect feature allows you to trac6 errors at sin(le record level althou(h you process records in Bul6. Example# HL@ create table t 2 x varchar02.93 "$T "ULL 3? Table created. HL@ declare 0 type array is table of varchar020//3? ; I l%data array #, array2 Ewor6s .E5 Ewor6s 0E5 / Etoo lon(5 much too lon(E5 1 Ewor6s IE5 "ULL5 Ewor6s 1E 3? U l%start number #, .? Q be(in J loop .9 be(in .. forall i in l%start .. l%data.count .0 insert into t values 2 l%data2i3 3? .; EPIT? .I exception ./ when others then .1 dbms%output.put%line2 EBad row index , E VV 2l%startTs<lOrowcount3 VV .U E E VV s<lerrm 3? .Q l%start #, l%start T s<lOrowcount T .? .J end? 09 end loop? 0. end? 00 R Bad row index , ; $&A89.I9.# inserted value too lar(e for column Bad row index , / $&A89.I99# cannot insert "ULL into 2W$KXTETW.WTW.WPW3 KLRHL procedure successfully completed. HL@ select = from t? P 8888888888 wor6s . wor6s 0 wor6s I wor6s 1 HL@ &a8in% Advanta%e of 3a$tition 3$unin% ------------------------------------ Lar(e tables are partitioned by 'BAs for better mana(eability5 administration and performance. Lou need to be aware of tables that are partitioned and write HL <ueries that could ta6e advanta(e of those partitions. *hen a <uery uses the conditions which are also used to create partitions5 $racle does a CKartition Krunin(D and scans records only in the relevant partitions5 thus savin( resources and improvin( performance. Example# !&EATE TABLE !!!%FA'%:$U&"AL%'ETAIL 2 KK%LI"E%I' "U)BE& 2./3 "$T "ULL5 KE&I$'%KA&T "U)BE& 2035 :$U&"AL%+EA'E&%I' "U)BE& 2./35 :$U&"AL%LI"E%"B& "U)BE& 2./35 KE&I$' GA&!+A&0 2./35 ET%$F%B$$N%I' "U)BE& 2./35 !$'E%!$)BI"ATI$"%I' "U)BE& 2./35 :$U&"AL%BAT!+ GA&!+A&0 2.9935 :$U&"AL%"A)E GA&!+A&0 2.9935 :$U&"AL%!ATEA$&L GA&!+A&0 20/35 :$U&"AL%'E!&IKTI$" GA&!+A&0 20I935 AFF%!$)KA"L GA&!+A&0 20/35 AFF%A!!$U"T GA&!+A&0 20/35 AFF%!E"TE& GA&!+A&0 20/35 AFF%BAE%GA&IABLE GA&!+A&0 20/35 AFF%)$'ALITL GA&!+A&0 20/35 AFF%)A&NET%EA)E"T GA&!+A&0 20/35 AFF%F$L'E& GA&!+A&0 20/35 AFF%K&$'U!T%$U&!E GA&!+A&0 20/35 AFF%'ETI"ATI$" GA&!+A&0 20/35 L$!AL%!U&&E"!L%A)$U"T "U)BE&5 L$!AL%!U&&E"!L%'B!&%I"'I!AT$& GA&!+A&0 2.35 :$U&"AL%T&A"A!TI$"%A)$U"T "U)BE&5 :$U&"AL%T&A"%'B!&%I"'I!AT$& GA&!+A&0 2.3 "$T "ULL5 T&A"A!TI$"%!U&&E"!L%!$'E GA&!+A&0 2./35 'ATE%!&EATE' 'ATE5 :$U&"AL%$U&!E GA&!+A&0 20/35 T&A"A!TI$"%!U&&E"!L%&ATE "U)BE&5 UE&%EHUE"!E "U)BE& 2./35 A!!$U"TI"A%'ATE 'ATE5 $&'E&%"U)BE& GA&!+A&0 2./935 I"GE"T$&L%ITE)%"U)BE& GA&!+A&0 2./935 HUA"TITL GA&!+A&0 2./935 U"IT%$F%)EAU&E GA&!+A&0 2./935 '$!U)E"T%"U)BE& GA&!+A&0 2./935 '$!U)E"T%'ATE GA&!+A&0 2./935 K&$:E!T%"U)BE& GA&!+A&0 2./935 '$!U)E"T%"U)BE&%T*$ GA&!+A&0 2./935 +IKKE'%'ATE GA&!+A&0 2./935 L%&EFE&E"!E%I' "U)BE&3 TABLEKA!E UE& K!TF&EE .9 K!TUE' I9 I"IT&A" .9 )APT&A" 0// T$&AAE 2 3 KA&TITI$" BL &A"AE 2KE&I$'%KA&T3 2 KA&TITI$" :$U&"L%'ETL9. GALUE LE T+A" 203 TABLEKA!E :$U&"L%'ETL9. 35 KA&TITI$" :$U&"L%'ETL90 GALUE LE T+A" 2;3 TABLEKA!E :$U&"L%'ETL90 35 KA&TITI$" :$U&"L%'ETL9; GALUE LE T+A" 2I3 TABLEKA!E :$U&"L%'ETL9; 35 KA&TITI$" :$U&"L%'ETL9I GALUE LE T+A" 2/3 TABLEKA!E :$U&"L%'ETL9I 35 KA&TITI$" :$U&"L%'ETL9/ GALUE LE T+A" 213 TABLEKA!E :$U&"L%'ETL9/ 35 KA&TITI$" :$U&"L%'ETL91 GALUE LE T+A" 2U3 TABLEKA!E :$U&"L%'ETL91 35 KA&TITI$" :$U&"L%'ETL9U GALUE LE T+A" 2Q3 TABLEKA!E :$U&"L%'ETL9U 35 KA&TITI$" :$U&"L%'ETL9Q GALUE LE T+A" 2J3 TABLEKA!E :$U&"L%'ETL9Q 35 KA&TITI$" :$U&"L%'ETL9J GALUE LE T+A" 2.93 TABLEKA!E :$U&"L%'ETL9J 35 KA&TITI$" :$U&"L%'ETL.9 GALUE LE T+A" 2..3 TABLEKA!E :$U&"L%'ETL.9 35 KA&TITI$" :$U&"L%'ETL.. GALUE LE T+A" 2.03 TABLEKA!E :$U&"L%'ETL.. 35 KA&TITI$" :$U&"L%'ETL.0 GALUE LE T+A" 2.;3 TABLEKA!E :$U&"L%'ETL.0 35 KA&TITI$" :$U&"L%'ETLIJ GALUE LE T+A" 2)APGALUE3 TABLEKA!E :$U&"L%'ETLIJ3 3? For this table if you want data for only last 0 periods5 it is better to have a filter on the column KE&I$'%KA&T than a date ran(e. This will ensure that $racle does partition prunin(. imilarly if you want to update all the records in this table5 instead of tryin( to do it at one shot5 split up the update partition8wise and run multiple partition updates in parallel. This will speed up the process manifolds. The issue to be considered here is to chec6 the available resources and decide on number of parallel processes. 3R*/ C &unin% "uidelines ------------------------ Use Pre"ompiler #p$ions ---------------------- Use +$L'%!U&$&,LE and &ELEAE%!U&$&,"$ pre8compiler options while pre8compilin(. Usin( these options when )$'E,A"I will not ma6e use of these options. These two parameters can be entered in a line in the pro(ram with the followin( syntax# EPE! $&A!LE $KTI$" 2+$L'%!U&$&,"$3? EPE! $&A!LE $KTI$" 2&ELEAE%!U&$&,LE3? )AP$KE"!U&$& 2default value .93 si(nifies the initial si7e of the pro(ram cursor cache. The si7e of the cursor cache may (row5 dependin( on the values of +$L'%!U&$& and &ELEAE%!U&$&. o5 its better to increase the )AP$KE"!U&$& value in pre8compilin( options.