Download presentation
Presentation is loading. Please wait.
Published byMargaret Wilson Modified over 9 years ago
1
Oracle PL/SQL Practices
2
Critical elements of PL/SQL Best Practices Build your development toolbox Unit test PL/SQL programs Optimize SQL in PL/SQL programs Manage errors effectively and consistently Write readable, maintainable code
3
High Level, High Impact Important principles... Assume everything will change. Aim for a single point of definition (a SPOD). Top four tips.... Drink lots of water. Write tiny chunks of code. Stop writing so much SQL. Stop guessing and start testing.
4
Let's read some code! Move blocks of complex code into the declaration section Replace them with descriptive names The code is now easier to read and maintain You can more easily identify areas for improvement
5
Anchor Declarations of Variables
6
Always Fetch into Cursor Records
7
Input Parameters
8
Select-in multi-columns
9
Update-set multi-columns
10
Avoid SQL-PL/SQL Naming Conflicts
11
Row Count
12
Performance Discussion
13
dynamic sql without bind variable DECLARE cur SYS_REFCURSOR; tmp crm_partner%ROWTYPE; BEGIN FOR j IN 1.. 200 LOOP OPEN cur FOR 'SELECT * FROM crm_partner p WHERE rownum <= '|| j; LOOP FETCH cur INTO tmp; EXIT WHEN cur%NOTFOUND; NULL; END LOOP; CLOSE cur; END LOOP; END; / PL/SQL procedure successfully completed Executed in 1.373 seconds
14
dynamic sql with bind variable DECLARE cur SYS_REFCURSOR; tmp crm_partner%ROWTYPE; BEGIN FOR j IN 1.. 200 LOOP OPEN cur FOR 'SELECT * FROM crm_partner p WHERE rownum <= :i' USING j; LOOP FETCH cur INTO tmp; EXIT WHEN cur%NOTFOUND; NULL; END LOOP; CLOSE cur; END LOOP; END; / PL/SQL procedure successfully completed Executed in 0.858 seconds
15
dynamic sql fetch all one time DECLARE cur SYS_REFCURSOR; TYPE type_tab IS TABLE OF crm_partner%ROWTYPE; tmp type_tab; BEGIN FOR j IN 1.. 200 LOOP OPEN cur FOR 'SELECT * FROM crm_partner p WHERE rownum <= :i' USING j; FETCH cur BULK COLLECT INTO tmp; FOR i IN 1.. tmp.count LOOP NULL; END LOOP; CLOSE cur; END LOOP; END; / PL/SQL procedure successfully completed Executed in 0.405 seconds
16
static cursor DECLARE CURSOR get_data(p_row_no IN NUMBER) IS SELECT * FROM crm_partner p WHERE rownum <= p_row_no; BEGIN FOR j IN 1.. 200 LOOP FOR i IN get_data(j)LOOP NULL; END LOOP; END; / PL/SQL procedure successfully completed Executed in 0.39 seconds
17
static cursor fetch all one time DECLARE CURSOR cur(p_row_no IN NUMBER) IS SELECT * FROM crm_partner p WHERE rownum <= p_row_no; TYPE type_tab IS TABLE OF crm_partner%ROWTYPE; tmp type_tab; BEGIN FOR j IN 1.. 200 LOOP OPEN cur(j); FETCH cur BULK COLLECT INTO tmp; FOR i IN 1.. tmp.count LOOP NULL; END LOOP; CLOSE cur; END LOOP; END; / PL/SQL procedure successfully completed Executed in 0.375 seconds
18
dml single insert/select or bulk collect/forall You should do it in a single SQL statement if at all possible. If you cannot do it in a single SQL Statement, then do it in PL/SQL. If you cannot do it in PL/SQL, try a Java Stored Procedure. If you cannot do it in Java, do it in a C external procedure. If you cannot do it in a C external routine, you might want to seriously
19
Bulk collect-For-Insert ops$tkyte%ORA11GR2> declare 2 type array is table of t1%rowtype index by binary_integer; 3 cursor test_curs is select * from t1; 4 l_data array; 5 begin 6 open test_curs; 7 loop 8 fetch test_curs bulk collect into l_data limit 2000; 9 for i in 1..l_data.COUNT 10 LOOP 11 insert into t2 values l_data(i); 12 END loop; 13 exit when test_curs%notfound; 14 END LOOP; 15 close test_curs; 16 end; 17 / PL/SQL procedure successfully completed.
20
Bulk collect-Forall-Insert ops$tkyte%ORA11GR2> declare 2 type array is table of t1%rowtype index by binary_integer; 3 cursor test_curs is select * from t1; 4 l_data array; 5 begin 6 open test_curs; 7 loop 8 fetch test_curs bulk collect into l_data limit 2000; 9 forall i in 1..l_data.COUNT 10 insert into t3 values l_data(i); 11 exit when test_curs%notfound; 12 END LOOP; 13 close test_curs; 14 end; 15 /
21
Insert-into-from insert into t4 select * from t1;
23
Switching between PL/SQL and SQL engines
24
Conventional Bind
25
Bulk Bind
26
Direct path inserts NOTE: a) it isn't necessarily faster in general. It does a direct path load to disk - bypassing the buffer cache. There are many cases - especially with smaller sets - where the direct path load to disk would be far slower than a conventional path load into the cache. b) a direct path load always loads above the high water mark, since it is formatting and writing blocks directly to disk - it cannot reuse any existing space. Think about this - if you direct pathed an insert of a 100 byte row that loaded say just two rows - and you did that 1,000 times, you would be using at least 1,000 blocks (never reuse any existing space) - each with two rows. Now, if you did that using a conventional path insert - you would get about 70/80 rows per block in an 8k block database. You would use about 15 blocks. Which would you prefer? c) you cannot query a table after direct pathing into it until you commit. (current session) d) how many people can direct path into a table at the same time? One - one and only one. It would cause all modifications to serialize. No one else could insert/update/delete or merge into this table until the transaction that direct paths commits. insert /*+ APPEND*/ into t4 select * from t1; Direct path inserts should be used with care, in the proper circumstances. A large load - direct path, but most of the time - conventional path.
27
direct path vs. conventional path
28
Thanks! Questions & Answers Shawn Huang (黄其晟) Data Architect Desk: +86.755.8621.8846 Mobile: +86.158.1728.0246 Email: shawn.huang@pactera.comshawn.huang@pactera.com
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.