Oracle - SQL-PL/SQL context switching

21
Technical Skills Enhancement – PL/SQL Best practices Context Switching

Transcript of Oracle - SQL-PL/SQL context switching

Page 1: Oracle - SQL-PL/SQL context switching

Technical Skills Enhancement – PL/SQL Best practices

Context Switching

Page 2: Oracle - SQL-PL/SQL context switching

Objectives

At the end of this training, you will be able to:

• Understand the concept of context switching and ways to avoid it

Page 3: Oracle - SQL-PL/SQL context switching

Agenda

– Context Switching

– Under the hood

– Reduce context switches - Avoid SQL in loops

– Bulk Bind to reduce context switches

– Syntax: Bulk Collect

– Syntax: FORALL

– Example of Bulk Collect & For All

– Bulk collect vs FOR Loop

– Best Practices in Bulk Collect – Using LIMIT

– Best Practices in Bulk Collect – Eliminating %NOTFOUND

Page 4: Oracle - SQL-PL/SQL context switching

Context Switching

• Context Switching– PL/SQL statements are run by the PL/SQL statement executor

– SQL statements in PL/SQL programs are run by the SQL statement executor.

– When the PL/SQL runtime engine encounters an SQL statement, it stops and passes the SQL statement over to the SQL engine.

– The SQL engine executes the SQL statement and returns information back to the PL/SQL engine (see Figure in the next slide).

– This transfer of control is called a context switch, and each one of these switches incurs overhead that slows down the overall performance of your programs.

Page 5: Oracle - SQL-PL/SQL context switching

Oracle server

PL/SQL Runtime Engine SQL Engine

PL/SQL block

Procedural statement executor

SQL statement executor

CURSOR c1 IS SELECT * FROM emp;

salsum integer;BEGIN salsum := 0; FOR emp_rec IN c1 LOOP

salsum := salsum+ emp_rec.sal; END LOOP ; dbms_output.put_line('Salary sum: ' || salsum);END ; Performance penalty Performance penalty

for many “context for many “context switches”switches”

Under the hood: SQL and PL/SQL – Context Switching

Page 6: Oracle - SQL-PL/SQL context switching

Reduce context switches - Avoid SQL in Loops• It's important to write efficient SQL ins id e PL/SQL

p ro g ra m s .• If you can replace a PL/SQL loop that executes a

SQL statement repetitively with a "pure" SQL statement, you are likely to get improved performance, for example: Instead of this:

Do this:

FOR rec IN (SELECT ename, sal FROM emp)LOOP UPDATE emp SET sal = rec.sal * 1.01 WHERE ename = rec.ename;END LOOP;

UPDATE emp SET sal = sal * 1.01;

Page 7: Oracle - SQL-PL/SQL context switching

Bulk Bind to reduce context switches

• Bulk Binding

– Bulk binding allows us to transfer rows between the SQL engine and the PLSQL engine as collections, thereby reducing time overhead caused due to context switching

– BULK COLLECT: SELECT statements that retrieve multiple rows with a single fetch, improving the speed of data retrieval

– FORALL: INSERTs, UPDATEs, and DELETEs that use collections to change multiple rows of data very quickly

Page 8: Oracle - SQL-PL/SQL context switching

Change in reqmt- back to too many context switches• Reqmt: check employees for eligibility for the increase in salary and if

they are eligible give a hike.

• Can’t do in a single SQLCREATE OR REPLACE PROCEDURE increase_sal2 ()

ISPROCEDURE check_eligibility(i_sal emp.sal%type,o_eligible OUT BOOLEAN) ISBEGIN---------- END;

BEGIN

FOR employee_rec IN (SELECT empno, sal FROM emp)

LOOP

check_eligibility (employee_rec.sal, l_eligible);

IF l_eligible THEN

UPDATE emp emp SET emp.sal = emp.sal+ emp.sal * increase_pct_in WHERE emp.empno =

employee_rec.empno;

END IF;

END LOOP;

END increase_sal2;

Number of UPDATE (DML SQL) statements fired by this PL/SQL program = Number of employees

Old way of

Implementation

Page 9: Oracle - SQL-PL/SQL context switching

How to reduce context switches

• Use the BULK COLLECT clause to fetch multiple rows into one or more collections with a single context switch.

• Use the FORALL statement when you need to execute the same DML statement repeatedly for different bind variable values. The UPDATE statement in the increase_salary procedure fits this scenario; the only thing that changes with each new execution of the statement is the employee ID.

Page 10: Oracle - SQL-PL/SQL context switching

Syntax: Bulk Collect • Definition

– Bulk Collect is used to bulk-bind output collections before returning to PL/SQL Engine

• Purpose of Bulk Collect

– To do bulk binds with SELECT statements. Select data from a table into a COLLECTION.

• Syntax:

SELECT <Column_Name(s)> BULK COLLECT

INTO <collection_name>

FROM <Table_Name>

WHERE <condition>;

• Example:

SELECT Deptno BULK COLLECT INTO my_Deptno_coll FROM Emp;

Page 11: Oracle - SQL-PL/SQL context switching

Syntax: FORALL

• Definition

FORALL statement is used for bulk-bind DML operations before sending them to SQL engine

• Purpose of FORALL– Use with INSERTs, UPDATEs and DELETEs

– Used for moving data from collections to tables

• Syntax:

FORALL <loop_variable> IN <Collection_type_Var>.FIRST..<Collection_Type_var>.LAST

Page 12: Oracle - SQL-PL/SQL context switching

A Different Process with FORALL

Oracle server

PL/SQL Runtime Engine SQL Engine

PL/SQL block

Procedural statement executor

SQL statement executor

DECLARETYPE sal_detail is

number(10,2) OF NUMBER;emplist NumList :=

NumList(10, 20, 30);BEGINFORALL i in

courses.FIRST..courses.LASTDELETE FROM

student where course_id = courses(i);END;

Much less overhead for Much less overhead for context switchingcontext switching

Page 13: Oracle - SQL-PL/SQL context switching

Example of Bulk Collect & For All ClauseCREATE OR REPLACE PROCEDURE increase_sal3 (

IS

PROCEDURE check_eligibility(i_sal emp.sal%type,o_eligible OUT BOOLEAN)

IS

BEGIN

------

END;

BEGIN

SELECT empno, sal BULK COLLECT INTO l_empnos FROM emp ;

FOR indx IN 1 .. l_empnos.COUNT

LOOP

check_eligibility (l_empnos(indx).l_sal,l_eligible);

IF l_eligible

THEN

l_eligible_ids (l_eligible_ids.COUNT + 1) := l_empnos(indx).l_empno;

END IF;

END LOOP;

FORALL indx IN 1 .. l_eligible_ids.COUNT

UPDATE emp emp SET emp.sal =emp.sal+ emp.sal * increase_pct_in

WHERE emp.empno = l_eligible_ids (indx);

END increase_sal3;

Using BULK COLLECT AND FORALL

Page 14: Oracle - SQL-PL/SQL context switching

Performance comparison

Script : BulkBind_PerfComparison

Page 15: Oracle - SQL-PL/SQL context switching

Bulk collect vs FOR Loop

• When would you choose a Cursor FOR Loop over BULK COLLECT?

•Whenever you want to do complex processing on each row as it is queried inside the loop – and possibly halt further fetching.

•Whenever you are retrieving many rows and cannot afford to use up the memory (large numbers of users).

•Otherwise, moving to BULK COLLECT is a smart move!

Page 16: Oracle - SQL-PL/SQL context switching

Bulk collect vs FOR Loop

• FORALL is always better than DML in a loop, but remember that single SQL is better than FORALL.

– Ie the below FORALL is not a good idea

SELECT TO_NUMBER(PNUM), PNAME BULK COLLECT INTO PARTS_TAB1 FROM PARTS1;

FORALL I IN 1 .. PARTS_TAB1.COUNT -- use FORALL statement

INSERT INTO PARTS2 VALUES (PARTS_TAB1(I).P_PNUM, PARTS_TAB1(I).P_PNAME);BETTER

INSERT INTO PARTS3 SELECT * FROM PARTS1;

Page 17: Oracle - SQL-PL/SQL context switching

Best Practices in Bulk Collect – Using LIMIT

Using LIMIT

•One of the most important facts to keep in mind when you start using performance enchantment features such as BULK COLLECT is that there is almost always a trade-off to be made somewhere.

•The tradeoff with BULK COLLECT, like so many other performance-enhancing features, is "run faster but consume more memory.“

•Specifically, memory for collections is stored in the program global area (PGA), not the system global area (SGA). SGA memory is shared by all sessions connected to Oracle Database, but PGA memory is allocated for each session. Thus, if a program requires 5MB of memory to populate a collection and there are 100 simultaneous connections, that program causes the consumption of 500MB of PGA memory.

Script : BulkBind_LIMIT.tst

Page 18: Oracle - SQL-PL/SQL context switching

Best Practices in Bulk Collect – Using LIMIT

Execution Time (secs)

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

Bulk collect without LIMIT : 0.1

Bulk collect with LIMIT 10 : 1.12

Bulk collect with LIMIT 100 : 0.18

Bulk collect with LIMIT 1000 : 0.1

Page 19: Oracle - SQL-PL/SQL context switching

Best Practices in Bulk Collect – Eliminating %NOTFOUND

• When you are using BULK COLLECT and collections to fetch data from your cursor, you should never rely on the cursor attributes (%NOTFOUND) to decide whether to terminate your loop and data processing.

Script : BulkBind_CursorAttributes.sql

Page 20: Oracle - SQL-PL/SQL context switching

Best Practices in Bulk Collect

Keep in mind while using BULK COLLECT:

•It can be used with all three types of collections: associative arrays, nested tables, and VARRAYs.

•The collection is always filled sequentially and densely, starting from index value 1.

•It is always safe to iterate through a collection from 1 to collection .COUNT when it has been filled with BULK COLLECT.

•The collection is empty when no rows are fetched.

•Always check the contents of the collection (with the COUNT method) to see if there are more rows to process.

•Ignore the values returned by the cursor attributes, especially %NOTFOUND.

Page 21: Oracle - SQL-PL/SQL context switching

Thank YouFeedback, Questions, Discussion