You are on page 1of 24

Structured Query Language Olivier Comte

Oracle – SQL training French CSO


Oracle SQL training
Session 3

• VIEW
• TRIGGER
• Optimization
– Indexes

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
2
VIEW

Save a query with a name. All the fields of the view must have a unique
name. It is a bad idea to define the ORDER BY statement into a view.
CREATE OR REPLACE VIEW view_name AS
SELECT …

MATERIALIZED VIEW
A materialized view is a view and a table. The result of the view is stored into a
table object of which the definition matches the view fields.
If the results of the view is changed, the table must be updated too manually: it is
not automatic!
Useful for:
• Very complex computations
• Merge data from various database

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
3
Optimization
Indexes: definition and syntax
o Index is a sorted list of values from one or more fields of a table paired the
internal rows number where they can be found in this table. It improves the
speed of data retrieval operations (SELECT) at the cost of additional writes and storage
space (INSERT, UPDATE).

create index Z_LPN_IDX1


on Z_LPN (CREATE_DTTM);

o Unique index is an index which warranties the uniqueness of the values. It is


both an index and a constraint.

create unique index Z_LPN_IDX2


on Z_LPN (LPN_NUMBER);

o Indexes improve the performance to resolve filter conditions


o Indexes, like tables, can become very fragmented when updated frequently,
so it is important to rebuild them frequently.

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
4
PL/SQL
TRIGGER
A trigger allows changing the behavior of Oracle when modifying the data on a table
(INSERT, UPDATE, DELETE). It can be executed before, after or instead of one of these
operations.

For each row:

:NEW and :OLD allow to get access to the rows before and after the modifications

=> When inserting new LPN details, if the user = JULIEN on the detail, define the quantity as
the sum of all the existing LPN details of the current LPN
CREATE OR REPLACE TRIGGER tib_z_lpn_detail BEFORE INSERT
ON z_lpn_detail FOR EACH ROW
DECLARE
v_quantity z_lpn_detail.quantity%TYPE;
BEGIN
SELECT COALESCE(SUM(quantity),0) INTO v_quantity
FROM z_lpn_detail
WHERE lpn_id = :NEW.lpn_id;
IF :NEW.USER_ID = 'JULIEN' THEN
:NEW.QUANTITY := v_quantity;
END IF;
END;
Warning: this simple trigger has an issue: « mutating trigger ».
Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
5
PL/SQL
TRIGGER
A trigger allows changing the behavior of Oracle when modifying the data on a table
(INSERT, UPDATE, DELETE). It can be executed before, after or instead of one of these
operations.

Whole table (no FOR EACH ROW)

Triggered after the entire command. At this stage, all the rows of the table are accessible but
we don’t know which rows are impacted by the modification.

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
6
PL/SQL
FUNCTION & PROCEDURE
A PROCEDURE is a group of PL/SQL statements which can be called by a name.
Some input or output parameters can be defined.
=> Create a procedure to get the quantities of a given item into an LPN. If the item
is part of a set, evaluate the quantities in term of sets.
Input: LPN_NUMBER, ITEM_BARCODE
Output: ITEM_BARCODE, QUANTITY
CREATE OR REPLACE PROCEDURE get_sku_quantity (
p_lpn_number IN z_lpn.lpn_number%type,
p_item_barcode IN OUT z_item.reference%type,
p_quantity OUT z_lpn_detail.quantity%type
)
IS
BEGIN
[...]
END;

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
7
PL/SQL
FUNCTION & PROCEDURE
CREATE OR REPLACE PROCEDURE get_sku_quantity (
p_lpn_number IN z_lpn.lpn_number%type,
p_item_barcode IN OUT z_item.reference%type,
p_quantity OUT z_lpn_detail.quantity%type
)
IS
BEGIN
SELECT
COALESCE(zi_set.reference, zi_lpn.reference) AS reference,
MIN(zld.quantity / COALESCE(zisd_set.quantity, 1 )) AS quantity
INTO p_item_barcode, p_quantity
FROM z_lpn zl
INNER JOIN z_lpn_detail zld ON zld.lpn_id = zl.id
INNER JOIN z_item zi_lpn ON zi_lpn.id = zld.item_id
LEFT JOIN (z_item_set_detail zisd_lpn
INNER JOIN z_item_set_header zish_set ON zish_set.id =
zisd_lpn.item_set_hdr_id
INNER JOIN z_item zi_set ON zi_set.id = zish_set.item_id
INNER JOIN z_item_set_detail zisd_set ON zish_set.id =
zisd_set.item_set_hdr_id)
ON zisd_lpn.item_id = zld.item_id
WHERE zl.lpn_number = p_lpn_number AND zi_lpn.reference = p_item_barcode
GROUP BY COALESCE(zi_set.reference, zi_lpn.reference);
EXCEPTION WHEN no_data_found THEN NULL;
END;

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
8
PL/SQL
FUNCTION & PROCEDURE
A FUNCTION is a procedure which returns a value (output parameter).
Some input or output parameters can be defined too.
In addition, a FUNCTION can be DETERMINISTIC which means the output values
only depend from input parameters.
=>Create a function to evaluate the number of working days between 2 dates
(exclude Saturdays and Sundays).
CREATE OR REPLACE FUNCTION get_working_day (
p_from_day IN DATE,
p_to_day IN DATE
)
RETURN INT
DETERMINISTIC
IS
BEGIN
[...]
END;

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
9
PL/SQL
FUNCTION & PROCEDURE
CREATE OR REPLACE FUNCTION get_working_day (
p_from_day IN DATE,
p_to_day IN DATE
)
RETURN INT
DETERMINISTIC
IS
v_result INT;
v_day_of_week CHAR(1);
v_from_day DATE :=TRUNC(p_from_day);
v_to_day DATE :=TRUNC(p_to_day);
BEGIN
IF v_from_day>v_to_day THEN
RETURN 0;
ELSE
v_result := 0;
WHILE v_from_day <= v_to_day LOOP
v_day_of_week := TO_CHAR(v_from_day,'D','NLS_DATE_LANGUAGE=AMERICAN');
IF v_day_of_week NOT IN ('1','7') THEN
v_result := v_result +1;
END IF;
v_from_day := v_from_day +1;
END LOOP;
RETURN v_result;
END IF;
END;
Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
10
PL/SQL
Autonomous transaction
Functions, procedures and triggers can be executed into an autonomous transaction in order to commit
the modifications independently from the transaction of the caller. A kind of second temporary session.

CREATE OR REPLACE PROCEDURE my_proc (


[...]
) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
[...]
END;

Useful for logging messages not rolled back when an error happens.

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
11
Optimization
Statistics and execution plan

o Oracle evaluates some statistics of each index & table to estimate the best
method to select when browsing into them.
o This method is called “execution plan” of the query.
o The execution plan can change across the life of the database, so it is
important to re-calculate the statistics often.
=>Check the last time when the statistics on indexes of Z_LPN has been re-
evaluated
select LAST_ANALYZED, INDEX_NAME
from USER_INDEXES
where INDEX_NAME in ('Z_LPN_IDX1', 'Z_LPN_IDX2', 'Z_LPN_PK')

RESULT
LAST_ANALYZED INDEX
04/10/2013 09:17:52 Z_LPN_IDX1
04/10/2013 09:17:57 Z_LPN_IDX2
03/10/2013 22:10:45 Z_LPN_PK

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
12
Optimization
Statistics and execution plan
ÞInsert 1 000 000 LPNs in the table Z_LPN with random CREATE_DTTM and
LAST_UPDATE_DTTM

declare
v_number_of_rows number(9);
begin
loop
insert into Z_LPN (ID, LPN_NUMBER, TYPE, STATUS, USER_ID, CREATE_DTTM,
LAST_UPDATE_DTTM)
select max(ID) over()
+ row_number() over(order by ID) as ID
, 'LPN'|| (max(ID) over() + row_number() over(order by ID))
as LPN_NUMBER
, 'I' as TYPE
, 10 as STATUS
, 'WM' as USER_ID
, current_timestamp+dbms_random.value(-4,4) as CREATE_DTTM
, current_timestamp+dbms_random.value(-4,4) as LAST_UPDATE_DTTM
from Z_LPN
where not exists(select 1 from Z_LPN where ID = 1000000);
v_number_of_rows := sql%rowcount;
commit;
exit when v_number_of_rows = 0;
end loop;
end;

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
13
Optimization
Statistics and execution plan
=>Update the created & last updated date of a LPN to a special date

ÞCompare the query to find back this LPN when browsing the created date or the last
updated date
select *
from z_lpn
where create_dttm between trunc(current_timestamp)+7
and trunc(current_timestamp)+8

select *
from z_lpn
where last_update_dttm between trunc(current_timestamp)+7
and trunc(current_timestamp)+8

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
14
Optimization
Statistics and execution plan
=>Re-evaluate the statistics and compare
Begin

dbms_stats.gather_table_stats(ownname => user, tabname => 'Z_LPN',


estimate_percent => dbms_stats.auto_sample_size);

End;

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
15
Optimization
High performance PL/SQL: memory

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
16
Optimization
High performance PL/SQL: memory
SGA contains package static constants (very few). Example:
Package PKG is
NonStaticConstant constant pls_integer := MySequence.nextval;
StaticConstant constant pls_integer := 42;
End PKG;
PGA contains session local data (duration: a call).
UGA contains package level data (duration: a session).

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
17
Optimization
High performance PL/SQL: Bulk processing with BULK COLLECT and FORALL
At least an order of magnitude performance improvement.
create or replace procedure MyProc( d in EMPLOYEE.DEPARTMENT_ID%type
, s in EMPLOYEE.SALARY%type
)
is
cursor EmpCur is
select EMPLOYEE_ID, SALARY, HIRE_DATE
from EMPLOYEE
where DEPARTMENT_ID = d;
begin
for rec in EmpCur
loop
adjust(rec, s);
update EMPLOYEE
set SALARY = rec.SALARY
where EMPLOYEE_ID = rec.EMPLOYEE_ID;
end loop;
end MyProc;

Row by row processing is inefficient!

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
18
Optimization
High performance PL/SQL: Bulk processing with BULK COLLECT and FORALL

A lot of « context switches » occurs!

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
19
Optimization
High performance PL/SQL: Bulk processing with BULK COLLECT and FORALL

• The solution is « bulk collect into » and « FORALL »:

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
20
Optimization
High performance PL/SQL: Bulk processing with BULK COLLECT and FORALL

• bulk collect: move data from tables into PL/SQL collections (SELECT
INTO).
Take care of unlimited bulk collect (memory!): use the LIMIT clause.
FETCH ... BULK COLLECT INTO ... LIMIT ...; with a cursor!

• forall: move data from PL/SQL collections into tables (INSERT, UPDATE and
DELETE).
SQL%BULK_ROWCOUNT = nbr of rows modified.
SAVE_EXCEPTION and SQL%BULKEXCEPTIONS to continue past the exceptions

• Before and after statement-level triggers only fire once per FORALL
statement. FORALL is a single statement.
• In 10g and +, Oracle will automatically optimize cursor FOR loops
without DML statement to BULK COLLECT.

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
21
Optimization
Other optimizations
SQL:
• Data type mismatches in "where" or "on" clause.
• Functions on columns. For instance the use of "isnull", "nvl" or
"coalesce" instead of "is null”

PL/SQL:
• Function result cache (11g and +, enterprise edition only)
Add RESULT_CACHE clause

• NoCOPY hint (passing parameters by reference instead of the default by


value)
• Pipelined table function
CURSOR(select...)
PARALLEL_ENABLE, PIPELINED and PIPE ROW(...) keywords

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
22
Questions

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
23
End of the third session!

MERCI !

Copyright 2014 Manhattan Associates, Inc. Strictly Confidential. Not for Distribution.
24

You might also like