SlideShare a Scribd company logo
1 of 90
#458: A New View of Database
Views
Michael Rosenblum
Dulcian, Inc.
www.dulcian.com
2 of 90
Who Am I? – “Misha”
 Oracle ACE
 Co-author of 3 books
 PL/SQL for Dummies
 Expert PL/SQL Practices
 Oracle PL/SQL Performance Tuning Tips & Techniques
(Rosenblum & Dorsey, Oracle Press, July 2014)
 Won ODTUG 2009 Speaker of the Year
 Known for:
 SQL and PL/SQL tuning
 Complex functionality
 Code generators
 Repository-based development
3 of 90
Views???
Common train of thought:
 Stored SQL queries
 Nothing to worry about
 Reasonably transparent and stackable
 Minimal impact
 Have been around forever…..
 (Usually implies)…and have never changed.
4 of 90
Views!!!
“Thick database” approach:
 Views can serve as an isolation layer
 UI should never talk to tables!
 Views can be easily changed.
 Views are editionable (EBR).
 Isolation can be bi-directional.
 Views are complex.
 Lots of new functionality in every version
 Can impact Cost Based Optimizer (CBO) decisions
 Side-effects and non-trivial impact
5 of 90
Outline
To be discussed:
 De-normalized views with INSTEAD OF triggers
 Function-based views
 Special cases:
 Compound triggers
 Cross-edition views
 Various performance considerations 
Will not be discussed:
 Object views
 Materialized views
6 of 90
Views: Functionality & Features
7 of 90
The Idea
View is (IMHO!):
 Data set, broadly defined at design-time and formed
at run-time.
 The definition may mutate via:
 Parameterized conditions
 Dynamic SQL
 This data set may accept DMLs
 Only on a per-row basis (no statement-level actions)
 Directly or via associated PL/SQL program units
 Set is not persistent and may need to be rebuilt to accept
DMLs.
8 of 90
The Reasoning
Logical denormalization is great:
 Less coding in the UI
 Transparent system design
 Long-term protection against data model changes
 Simplified testing
9 of 90
Basics
10 of 90
create or replace view scott.v_emp
as
select e.empno,
e.ename,
e.deptno,
d.dname,
e.sal
from scott.emp e,
scott.dept d
where e.deptno=d.deptno
Basic Code 
11 of 90
select *
from dba_updatable_columns
where table_name = 'V_EMP'
COLUMN_NAME UPDATABLE INSERTABLE DELETABLE
--------------- --------------- ------------- ---------
EMPNO YES YES YES
ENAME YES YES YES
DEPTNO YES YES YES
DNAME NO NO NO
SAL YES YES YES
Direct DML…Sometimes
12 of 90
create or replace trigger scott.v_emp_iu
instead of update on scott.v_emp
begin
if :new.sal!=:old.sal then
if sys_context ('userenv','CLIENT_INFO')='SalMaint'
then
update emp
set sal = :new.sal
where empno = :old.empno;
else
raise_application_error
(-20001,'Not enough privileges');
end if;
else
update emp
set ename = :new.ename
where empno = :old.empno;
end if;
end;
INSTEAD-OF – Functionality
13 of 90
exec scott.runStats_pkg.rs_start;
alter trigger scott.v_emp_iu disable;
begin
for i in 1..10000 loop
update scott.v_emp set ename=ename where empno = 7782;
end loop;
end;
/
exec scott.runStats_pkg.rs_middle;
alter trigger scott.v_emp_iu enable;
begin
for i in 1..10000 loop
update scott.v_emp set ename=ename where empno = 7782;
end loop;
end;
/
exec scott.runStats_pkg.rs_stop;
Run1 ran in 35 cpu hsecs
Run2 ran in 77 cpu hsecs
run 1 ran in 45.45% of the time
Name Run1 Run2 Diff
STAT...CPU used by this session 36 79 43
STAT...execute count 10,037 20,036 9,999
STAT...session logical reads 40,441 50,480 10,039
INSTEAD-OF – Extra Cost
What???
14 of 90
DMLs Against Views
15 of 90
DML Implementation
UPDATE on view = SELECT + UPDATE
DELETE on view = SELECT + DELETE
INSERT on view = Only INSERT
16 of 90
Test Case (1)
CREATE TYPE test_tab_ot AS OBJECT (owner_tx VARCHAR2(30),
name_tx VARCHAR2(30),
object_id NUMBER,
type_tx VARCHAR2(30));
CREATE TYPE test_tab_nt IS TABLE OF test_tab_ot;
CREATE FUNCTION f_searchTestTab_tt (i_type_tx VARCHAR2) RETURN test_tab_nt
IS
v_out_tt test_tab_nt;
begin
SELECT test_tab_ot(owner, object_name, object_id, object_type)
BULK COLLECT INTO v_out_tt
FROM test_tab
WHERE object_type = i_type_tx;
dbms_output.put_line('Inside f_searchTestTab_tt:'||v_out_tt.count);
RETURN v_out_tt;
END;
17 of 90
Test Case (2)
create or replace view v_search_table as
select *
from table(f_searchtesttab_tt('TABLE'));
create or replace trigger v_search_table_iiud
instead of insert or update or delete on v_search_table
begin
if inserting then
dbms_output.put_line('Insert');
elsif updating then
dbms_output.put_line('Update');
elsif deleting then
dbms_output.put_line(‘Delete');
end if;
end;
18 of 90
DML Check
SQL> INSERT INTO v_search_table (object_id, name_tx)
2 VALUES (-1,'A');
Insert
1 row created.
SQL> UPDATE v_search_table SET name_tx = 'Test‘
2 WHERE object_id = 5;
Inside f_searchTestTab_tt:1571
Update
1 row updated.
SQL> DELETE FROM v_search_table WHERE object_id = 5;
Inside f_searchTestTab_tt:1571
Delete
1 row deleted.
Function is not fired!
Process all to update one?
19 of 90
Important!
To fire INSTEAD OF UPDATE/DELETE,
Oracle must locate row first.
Oracle must have the whole resulting set
available to filter it
 … but you can cheat 
20 of 90
Parameterized View (1)
CREATE PACKAGE global_pkg IS
v_object_id NUMBER;
END;
CREATE FUNCTION f_searchTestTab_tt (i_type_tx varchar2) RETURN
test_tab_nt is
v_out_tt test_tab_nt;
BEGIN
IF global_pkg.v_object_id IS NULL THEN
SELECT test_tab_ot(owner, object_name, object_id, object_type)
BULK COLLECT INTO v_out_tt
FROM test_tab
WHERE object_type = i_type_tx;
ELSE
SELECT test_tab_ot(owner, object_name, object_id, object_type)
BULK COLLECT INTO v_out_tt
FROM test_tab
WHERE object_id = global_pkg.v_object_id;
END IF;
dbms_output.put_line
('Inside f_searchTestTab_tt:'||v_out_tt.count);
RETURN v_out_tt;
END;
Usage (if needed)
Global parameter
21 of 90
Parameterized View (2)
SQL> BEGIN global_pkg.v_object_id:=5; END;
2 /
SQL> UPDATE v_search_table SET name_tx = 'Test'
2 WHERE object_id = 5;
Inside f_searchTestTab_tt:1
Update
1 row updated.
SQL> DELETE FROM v_search_table WHERE object_id = 5;
Inside f_searchTestTab_tt:1
Delete
1 row deleted.
22 of 90
Parameterized View (3)
SQL> exec runstats_pkg.rs_start;
SQL> BEGIN
2 global_pkg.v_object_id:=NULL;
3 FOR i IN 1..100 LOOP
4 UPDATE v_search_table SET name_tx = 'Test'||i
5 WHERE object_id = 5;
6 END LOOP;
7 END;
8 /
SQL> exec runstats_pkg.rs_middle;
SQL> BEGIN
2 global_pkg.v_object_id:=5;
3 FOR i IN 1..100 LOOP
4 UPDATE v_search_table SET name_tx = 'Test'||i
5 WHERE object_id = 5;
6 END LOOP;
7 END;
8 /
SQL> exec runstats_pkg.rs_stop;
Run1 ran in 181 cpu hsecs
Run2 ran in 28 cpu hsecs
run 1 ran in 646.43% of the time
5x improvement
23 of 90
Compound Triggers on Views
24 of 90
Alternative to INSTEAD OF
You can also create a COMPOUND trigger
instead of an INSTEAD OF trigger 
 Trigger with common program area
Impact
 Pro:
 Common program area – possible to share code and
global variables  simulating statement-level BEFORE
event (sorry, there is no way to simulate an AFTER event)
 Con:
 Not very stable in 11g
25 of 90
CREATE OR REPLACE PACKAGE counter_pkg IS
v_nr NUMBER:=0;
PROCEDURE p_check;
procedure p_up;
END;
CREATE OR REPLACE PACKAGE BODY counter_pkg IS
PROCEDURE p_check is
BEGIN
dbms_output.put_line('Fired:'||counter_pkg.v_nr);
counter_pkg.v_nr:=0;
END;
procedure p_up is
begin
counter_pkg.v_nr:=counter_pkg.v_nr+1;
end;
END;
create or replace function f_securityCheck_yn return varchar2 is
begin
counter_pkg.p_up;
if sys_context ('USERENV', 'CLIENT_INFO') ='SalMaint' then
return 'Y';
else
return 'N';
end if;
end;
create function f_change_nr (i_nr number) return number is
begin
counter_pkg.p_up;
return i_nr+1;
end;
Monitoring tool
26 of 90
CREATE OR REPLACE TRIGGER v_search_table_IIUD
INSTEAD OF INSERT OR UPDATE OR DELETE ON v_search_table
BEGIN
if f_securityCheck_yn = 'Y' then
IF INSERTING THEN dbms_output.put_line('Insert');
ELSIF UPDATING THEN dbms_output.put_line('Update');
ELSIF DELETING THEN dbms_output.put_line('Delete');
END IF;
end if;
END;
create or replace trigger v_search_table_IIUD_comp
for insert or update or delete on v_search_table
COMPOUND TRIGGER
v_check_yn varchar2(1);
instead of each row is
begin
if v_check_yn is null then
v_check_yn:=f_securityCheck_yn;
end if;
if v_check_yn = 'Y' then
IF INSERTING THEN dbms_output.put_line('Insert');
ELSIF UPDATING THEN dbms_output.put_line('Update');
ELSIF DELETING THEN dbms_output.put_line('Delete');
END IF;
end if;
end instead of each row;
end;
Performance impact (1)
Common area
27 of 90
SQL> alter trigger v_search_table_IIUD_COMP disable;
SQL> alter trigger v_search_table_IIUD enable;
SQL> update v_search_table set name_tx = 'Test';
Inside f_searchTestTab_tt:1571
1571 rows updated.
SQL> exec counter_pkg.p_check;
Fired:1571
SQL> alter trigger v_search_table_IIUD_COMP enable;
SQL> alter trigger v_search_table_IIUD disable;
SQL> update v_search_table set name_tx = 'Test';
Inside f_searchTestTab_tt:1571
1571 rows updated.
SQL> exec counter_pkg.p_check;
Fired:1
SQL> exec dbms_application_info.set_client_info('SalMaint');
SQL> update v_search_table set name_tx = 'Test';
Inside f_searchTestTab_tt:1571
Update
Update
....
1571 rows updated.
SQL> exec counter_pkg.p_check;
Fired:1
Performance impact (2)
Only one call!
28 of 90
Dangers of Logical Primary Keys
29 of 90
The Real Story
Synthetic primary keys on views
 Sometimes required by front-end environments (to
uniquely identify the row in the cache)
 Extremely dangerous if blindly used for
INSERT/UPDATE/DELETE
30 of 90
Test Case
CREATE OR REPLACE VIEW v_test_tab AS
SELECT 'Main|'||object_id pk_tx,
a.*
FROM test_tab_main a
UNION ALL
SELECT 'Other|'||object_id pk_tx,
a.*
FROM test_tab_other a;
31 of 90
Performance Impact
SQL> set autotrace traceonly explain
SQL> UPDATE v_test_tab
2 SET object_name='Test'
3 WHERE pk_tx='Main|1';
1 row updated.
Execution Plan
----------------------------------------------------------
Plan hash value: 3568876726
-------------------------------------------------------------------------
|Id| Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
| 0| UPDATE STATEMENT | | 500 | 45500 | 236 (1)|
| 1| UPDATE | V_TEST_TAB | | | |
| 2| VIEW | V_TEST_TAB | 500 | 45500 | 236 (1)|
| 3| UNION-ALL | | | | |
|*4| TABLE ACCESS FULL| TEST_TAB_MAIN | 15 | 330 | 9 (0)|
|*5| TABLE ACCESS FULL| TEST_TAB_OTHER | 485 | 14550 | 227 (1)|
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter('Main|'||TO_CHAR("OBJECT_ID")='Main|1')
5 - filter('Other|'||TO_CHAR("OBJECT_ID")='Main|1')
Full-table scans!
32 of 90
Optimization of UPDATEs
33 of 90
Resource Issues
Problem
 INSTEAD-OF UPDATE triggers often reference all
columns of the underlying tables
 … instead of trying to figure out what has been changed.
 UNDO is generated for all columns mentioned in
the UPDATE statement
 … regardless of whether they were changed or not
 … which causes major I/O overhead.
Alternative:
 Use Dynamic SQL to modify only changed columns
 … i.e. trade CPU utilization for better I/O!
34 of 90
Regular Trigger
create or replace trigger v_test_tab_iu
instead of update on v_test_tab
begin
if :new.object_type=‘TABLE' then
update test_tab_main
set owner=:new.owner, object_name=:new.object_name,
subobject_name=:new.subobject_name,
object_type=:new.object_type,
created=:new.created, last_ddl_time=:new.last_ddl_time,
timestamp=:new.timestamp, status=:new.status,
temporary=:new.temporary, generated=:new.generated,
secondary=:new.secondary, namespace=:new.namespace,
edition_name=:new.edition_name, sharing=:new.sharing,
editionable=:new.editionable,
oracle_maintained=:new.oracle_maintained
where object_id=:old.object_id;
else
update test_tab_other
set << the same list of columns as above >>
where object_id=:old.object_id;
end if;
end;
35 of 90
Dynamic SQL Trigger (1)
create or replace trigger v_test_tab_dynamic_iu
instead of update on v_test_tab
declare
v_main_rec test_tab_main%rowtype;
v_mainupdate_tx varchar2(32767);
v_other_rec test_tab_other%rowtype;
v_otherupdate_tx varchar2(32767);
begin
if :new.object_type='table' then
-- compare old/new for each attribute
if :old.object_name is null and :new.object_name is not null
or :old.object_name is not null and :new.object_name is null
or :old.object_name!=:new.object_name then
v_main_rec.object_name:=:new.object_name;
v_mainupdate_tx:=v_mainupdate_tx||
case
when v_mainupdate_tx is not null then ','
else null
end||chr(10)||
' object_name=v_rec.object_name';
end if;
...
Store new value
(if changed)
36 of 90
Dynamic SQL Trigger (2)
v_main_rec.object_id:=:old.object_id;
v_mainupdate_tx:=
'declare '||chr(10)||
' v_rec test_tab_main%rowtype:=:1;'||chr(10)||
'begin '||chr(10)||
' update test_tab_main ' ||chr(10)||
' set '||v_mainupdate_tx||chr(10)||
' where object_id=v_rec.object_id;'||chr(10)||
'end;';
execute immediate v_mainupdate_tx using v_main_rec;
else
<< the same logic as above for test_tab_other >>
end if;
end;
37 of 90
Performance Tradeoff
SQL> exec runstats_pkg.rs_start;
<< enable Dynamic trigger>>
SQL> begin 2 for i in 1..10000 loop
3 UPDATE v_test_tab SET object_name='Test'||i WHERE object_id = 5;
4 end loop;
5 END;
6 /
SQL> exec runstats_pkg.rs_middle;
<< enable regular trigger and rerun the same logic>>
SQL> exec runstats_pkg.rs_stop;
Run1 ran in 390 cpu hsecs
Run2 ran in 496 cpu hsecs
run 1 ran in 78.63% of the time
Name Run1 Run2 Diff
STAT...recursive calls 20,329 30,244 9,915
STAT...execute count 20,102 30,095 9,993
STAT...undo change vector size 2,495,476 938,552 -1,556,924
STAT...redo size 5,820,096 2,772,332 -3,047,764
Run1 latches total versus runs -- difference and pct
Run1 Run2 Diff Pct
136,486 184,679 48,193 73.90%
More CPU time
Much less I/O
38 of 90
PL/SQL Functions and Views
39 of 90
Setup
 Functions can be used as columns in views:
CREATE FUNCTION f_isEastCoast_yn (i_deptno NUMBER)
RETURN VARCHAR2
IS
v_out_yn varchar2(1);
BEGIN
SELECT CASE WHEN loc IN ('NEW YORK', 'BOSTON') THEN 'Y'
ELSE 'N'
END
INTO v_out_yn
FROM dept
WHERE deptno = i_deptno;
RETURN v_out_yn;
END;
CREATE VIEW v_emp_loc
AS
SELECT emp.empno, emp.ename, emp.deptno,
f_isEastCoast_yn(deptno) eastCoast_yn
FROM emp;
Returns Y/N
40 of 90
Problem
Default behavior:
SQL> SELECT column_name, data_type, data_length
2 FROM user_tab_columns
3 WHERE table_name = 'V_EMP_LOC'
4 ORDER by column_id;
COLUMN_NAME DATA_TYPE DATA_LENGTH
--------------- --------------- -----------
EMPNO NUMBER 22
ENAME VARCHAR2 10
DEPTNO NUMBER 22
EASTCOAST_YN VARCHAR2 4000
Over-allocation can impact front-end and middle-tier
that may read the Oracle Data Dictionary.
In the case of materialized views – storage over-allocation
41 of 90
Solution
CREATE OR REPLACE VIEW v_emp_loc AS
SELECT emp.empno, emp.ename, emp.deptno,
cast(f_isEastCoast_yn(deptno) as VARCHAR2(1)) eastCoast_yn
FROM emp
SQL> SELECT column_name, data_type, data_length
2 FROM user_tab_columns
3 WHERE table_name = 'V_EMP_LOC'
4 ORDER by column_id;
COLUMN_NAME DATA_TYPE DATA_LENGTH
--------------- --------------- -----------
EMPNO NUMBER 22
ENAME VARCHAR2 10
DEPTNO NUMBER 22
EASTCOAST_YN VARCHAR2 1
Exact allocation
42 of 90
Views and ORDER BY Danger
43 of 90
SELECT and ORDER BY (1)
 Output:
SQL> SELECT empno, ename, f_change_nr(empno) change_nr
2 FROM emp WHERE deptno = 20
3 ORDER BY 3;
5 rows selected.
SQL> exec counter_pkg.p_check;
Fired: ?
SQL> SELECT empno, change_nr
2 FROM (SELECT empno, ename, f_change_nr(empno) change
3 FROM emp WHERE deptno = 20
4 ORDER BY 3);
5 rows selected.
SQL> exec counter_pkg.p_check;
Fired: ?
In-line view causes
double-firing
5
10
 Problem:
 Why does the inline view cause a double fire?
44 of 90
SELECT and ORDER BY (2)
 Research of 10053 trace:
Order-by elimination (OBYE)
***************************
OBYE: OBYE performed.
OBYE: OBYE bypassed: no order by to eliminate.
Final query after transformations:*** UNPARSED QUERY IS ***
SELECT "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME",
"SCOTT"."F_CHANGE_NR"("EMP"."EMPNO") "CHANGE_NR"
FROM "SCOTT"."EMP" "EMP"
WHERE "EMP"."DEPTNO"=20
ORDER BY "SCOTT"."F_CHANGE_NR"("EMP"."EMPNO")
 Explanation:
 ORDER BY elimination is fired before the query
transformation.
 It does not find an ORDER BY clause in the root SELECT
and stops.
 After query transformation, ORDER BY suddenly appears.
 It is not removed now.
45 of 90
SELECT and ORDER BY (3)
 /*+ NO_MERGE */ hint solves the problem:
SQL> select empno, change_nr
2 from (select /*+ no_merge */
3 empno, ename, f_change_nr(empno) change_nr
4 from emp where deptno = 20 order by 3);
5 rows selected.
SQL> exec counter_pkg.p_check;
Fired: ?
 Why bother? Because of real views:
SQL> create or replace view v_emp as
2 select empno, ename, f_change_nr(empno) change_nr
3 from emp where deptno = 20
4 order by 3;
view created.
SQL> select empno, change_nr from v_emp;
5 rows selected.
SQL> exec counter_pkg.p_check;
Fired: ?
Query rewrite is skipped. 
ORDER BY elimination
is applied directly.
Same effect
as in-line view
5
10
46 of 90
Important!
ORDER BY clauses in views should be used
very cautiously and preferably avoided
altogether
 … because the CBO is still not magic.
47 of 90
Hints and Views
48 of 90
Problem
Yes, there are cases when hints are needed.
Hints are easy to add if you have a single-level
query.
If you are using views:
 Straightforward if you are lucky and can change
underlying views. 
 Doable otherwise, but may be tricky.
49 of 90
Solution #1
 Explicit naming of SELECT statements (20 char limit):
create or replace view scott.v_emp
as
select /*+ QB_NAME(V_EMP_Main) */
e.empno,
e.ename,
e.deptno,
d.dname,
e.sal
from scott.emp e,
scott.dept d
where e.deptno=d.deptno
50 of 90
Solution #1 - Proof
SQL> select /*+ FULL(@V_EMP_Main e) */ *
2 from v_emp
3 where empno=7369;
EMPNO ENAME DEPTNO DNAME SAL
---------- ---------- ---------- -------------- ----------
7369 SMITH 20 RESEARCH 800
Execution Plan
----------------------------------------------------------
Plan hash value: 3625962092
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 |
| 1 | NESTED LOOPS | | 1 | 30 |
| 2 | NESTED LOOPS | | 1 | 30 |
|* 3 | TABLE ACCESS FULL | EMP | 1 | 17 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 |
----------------------------------------------------------------
51 of 90
Solution #2
 Find Oracle-generated object alias:
SQL> explain plan for select * from v_emp where empno=7369;
Explained.
SQL> select * from table(dbms_xplan.display(null,null,'All'));
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 |
| 1 | NESTED LOOPS | | 1 | 30 |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 17 |
|* 3 | INDEX UNIQUE SCAN | PK_EMP | 1 | |
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 |
|* 5 | INDEX UNIQUE SCAN | PK_DEPT | 1 | |
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$F5BB74E1
2 - SEL$F5BB74E1 / E@SEL$2
3 - SEL$F5BB74E1 / E@SEL$2
4 - SEL$F5BB74E1 / D@SEL$2
5 - SEL$F5BB74E1 / D@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."EMPNO"=7369)
5 - access("E"."DEPTNO"="D"."DEPTNO")
52 of 90
Solution #2 - Proof
SQL> select /*+ FULL(@SEL$2 e) */ *
2 from v_emp
3 where empno=7369;
EMPNO ENAME DEPTNO DNAME SAL
---------- ---------- ---------- -------------- ----------
7369 SMITH 20 RESEARCH 800
Execution Plan
----------------------------------------------------------
Plan hash value: 3625962092
----------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 |
| 1 | NESTED LOOPS | | 1 | 30 |
| 2 | NESTED LOOPS | | 1 | 30 |
|* 3 | TABLE ACCESS FULL | EMP | 1 | 17 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 |
----------------------------------------------------------------
53 of 90
Keep in mind…
Naming all subqueries costs you nothing, but
makes production support much easier.
Warnings:
 Names may be ignored:
 If two or more query blocks have the same name
 If the same query block is hinted twice with different
name
 Beware of query transformation!
54 of 90
Editioning Views
55 of 90
Concept
Editioning view (Edition-Based Redefition):
 Can be created only for edition-enabled users
 Can have multiple versions
 Lots of restrictions (no joins, conditions, grouping
etc.) ~ more or less a synonym to the table
-- Parent Edition
create or replace editioning view scott.v_emp_ed
as select empno, ename, hiredate from scott.emp;
-- Child Edition (new column TIMESTAMP instead of DATE)
create or replace editioning view scott.v_emp_ed
as select empno, ename, hiredate_ts from scott.emp;
56 of 90
New Functionality
 Editioning views may have the same triggers as tables
-- Child edition: only new data
create or replace trigger v_emp_ed_bu
before update on v_emp_ed for each row
Begin
if :new.hiredate_ts <= to_timestamp('20150101','YYYYMMDD')
then
raise_application_error(-20001,'Data is too old');
end if;
end;
-- Parent edition: only old data
create or replace trigger v_emp_ed_bu
before update on v_emp_ed for each row
Begin
if :new.hiredate > to_date('20150101','YYYYMMDD')
then
raise_application_error(-20001,'Data is too new');
end if;
end;
57 of 90
Syntax News
58 of 90
Views
Multiple triggers of the same type:
 FOLLOWS <trigger> clause
Triggers can be created in DISABLED state.
Create invalid view (for later recompilation):
 FORCE clause
59 of 90
Views with Constraints (1)
 Making view non-updatable
 WITH READ ONLY clause
create or replace view scott.v_emp as
select e.empno,e.ename, e.deptno, d.dname, e.sal
from scott.emp e,
scott.dept d
where e.deptno=d.deptno
with read only constraint V_EMP_RO
SQL> select constraint_name, constraint_type, table_name
2 from user_constraints
3 where table_name = 'V_EMP';
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME
----------------- --------------- ---------------------
V_EMP_RO O V_EMP
60 of 90
Views with Constraints (2)
 WITH CHECK OPTION clause ~ Check constraint
 Insert/Update for single-table views
 Update is validated for multi-table views
 Insert causes “ORA-01733: virtual column not allowed here”
 Delete blocked if you have self-join
create or replace view scott.v_emp as
select e.empno, e.ename, e.deptno, d.dname, e.sal
from scott.emp e,
scott.dept d
where e.deptno=d.deptno
and d.deptno !=30
with check option constraint V_EMP_C
SQL> select constraint_name, constraint_type, table_name
2 from user_constraints
3 where table_name = 'V_EMP';
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION
----------------- --------------- ---------- ----------------
V_EMP_C V V_EMP NULL
You cannot see
condition 
61 of 90
Views with Constraints (3)
 Primary/Unique key – documentation/CBO only
create or replace view scott.v_emp (
empno,
ename,
deptno,
dname,
sal,
constraint v_emp_pk
primary key(empno) rely disable novalidate,
constraint v_emp_uk
unique (ename) rely disable novalidate
) as
select e.empno, e.ename, e.deptno, d.dname, e.sal
from scott.emp e,
scott.dept d
where e.deptno=d.deptno
62 of 90
SQL Text Expansion (1)
Problem:
 Views can be based on views that can be based on
views …
 How can you read what is really accessed?
Solution (12c-only)
 DBMS_UTILITY.EXPAND_SQL_TEXT
63 of 90
SQL Text Expansion (2)
SQL> declare
2 v_tx varchar2(32767);
3 begin
4 dbms_utility.expand_sql_text
5 ('select * from scott.v_emp', v_tx);
6 dbms_output.put_line(v_tx);
7 end;
8 /
SELECT "A1"."EMPNO" "EMPNO","A1"."ENAME"
"ENAME","A1"."DEPTNO" "DEPTNO","A1"."DNAME"
"DNAME","A1"."SAL" "SAL" FROM (SELECT "A3"."EMPNO"
"EMPNO","A3"."ENAME" "ENAME","A3"."DEPTNO"
"DEPTNO","A2"."DNAME" "DNAME","A3"."SAL" "SAL" FROM
"SCOTT"."EMP" "A3","SCOTT"."DEPT" "A2" WHERE
"A3"."DEPTNO"="A2"."DEPTNO" AND "A3"."EMPNO"<>30) "A1"
64 of 90
Real Business Cases
65 of 90
Storytelling
#1 Views and front-end
#2: Views as logical isolation
#3: When to stop
#4: Views as architectural tools
66 of 90
Story #1: Views and Front-End
67 of 90
How to Talk to Front-End
Developers
Problem:
 How to explain the importance of views to front-end
developers?
Solution:
 Explain the idea of roundtrip minimization!
68 of 90
Practical Aspects (1)
Existing implementations:
 Multiple separate requests to populate the screen
 Total number of roundtrips sometimes in thousands
for a single screen
 Each request is cheap.
 Total cost on all levels (DB/network/app server) is huge.
69 of 90
Web Application Architecture
3. Application
Server
2. Send data from
Client to app server
5. Database
6. Return Data from
database to app server
1. Client
4. Send data from
app server to database
7. Data in
Application Server
8. Return data from
app server to client
9. Data in
client
70 of 90
Practical Aspects (2)
Alternative:
 A view where 1 row gets all data to populate one
screen  1 round-trip
 Since not a lot of data is being returned, the complexity of
such a view can be pretty high.
 Very often, you trade off higher memory utilization for
less network requests.
71 of 90
Web Application
Architecture
3. Application
Server
2. Send data from
Client to app server
5. Database
6. Return Data from
DB to app server
1. Client
4. Send data from
app server to DB
7. Data in
Application Server
8. Return data from
app server to client
9. Data in
client
Data
UI views
72 of 90
Story #2: Views as Logical Isolation
73 of 90
History
Existing system:
 Major part of the solution requires data transformation
via global temporary tables (session-level)
 Significant scaling (from 150 to 2500 users)
Impact:
 Numerous log file switches  significant
performance impact
 LogMiner shows that ~ 75% of DMLs are related to
GTT!
74 of 90
New Knowledge
Session-level GTTs are subject to transaction
activities  Even though there is no
COMMIT, there is a ROLLBACK:
 INSERT
 Very little UNDO is generated: It is enough to generate
the DELETE entry using ROWID as a unique identifier.
 UPDATE
 As it does for the actual table, Oracle needs to preserve
the pre-DML state of the row.
 DELETE
 The entire row should be preserved to be restored if
needed.
75 of 90
Solution (1)
Views based on package variables require:
 Object collection
 Package to store
 Very non-trivial triggers 
CREATE TYPE dept_gtt_ot IS OBJECT
(deptno NUMBER,
dname VARCHAR2(14),
loc VARCHAR2(13))
/
CREATE TYPE dept_gtt_nt IS TABLE OF dept_gtt_ot
/
76 of 90
CREATE OR REPLACE PACKAGE dept_gtt_pkg IS
TYPE pk_tt IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
v_pk_tt pk_tt;
v_dept_tt dept_gtt_nt:=dept_gtt_nt();
FUNCTION f_getDept_tt RETURN dept_gtt_nt;
END;
/
CREATE OR REPLACE PACKAGE BODY dept_gtt_pkg IS
FUNCTION f_getDept_tt RETURN dept_gtt_nt IS
BEGIN
RETURN v_dept_tt;
END;
END;
/
CREATE OR REPLACE VIEW v_dept_gtt AS
SELECT *
FROM TABLE(dept_gtt_pkg.f_getDept_tt)
/
Solution (2)
77 of 90
CREATE OR REPLACE TRIGGER V_DEPT_GTT_IIUD
INSTEAD OF INSERT OR DELETE OR UPDATE ON V_DEPT_GTT
BEGIN
IF INSERTING THEN
IF :new.deptno IS NULL THEN
raise_application_error(-20001,'Deptno is mandatory');
END IF;
IF dept_gtt_pkg.v_pk_tt.exists(:new.deptno) THEN
raise_application_error(-20001,'Dept already exists');
END IF;
dept_gtt_pkg.v_dept_tt.extend;
dept_gtt_pkg.v_pk_tt(:new.deptno)
:=dept_gtt_pkg.v_dept_tt.last;
dept_gtt_pkg.v_dept_tt(dept_gtt_pkg.v_dept_tt.last):=
dept_gtt_ot(:new.deptno,:new.dname,:new.loc);
ELSIF DELETING THEN
IF :old.deptno IS NOT NULL AND
dept_gtt_pkg.v_pk_tt.exists(:old.deptno)
THEN
dept_gtt_pkg.v_dept_tt.delete
(dept_gtt_pkg.v_pk_tt(:old.deptno));
dept_gtt_pkg.v_pk_tt.delete(:old.deptno);
END IF;
...
Solution (3)
78 of 90
ELSIF UPDATING THEN
IF :new.deptno IS NOT NULL AND :old.deptno!=:new.deptno THEN
IF dept_gtt_pkg.v_pk_tt.exists(:new.deptno) THEN
raise_application_error
(-20001,'Cannot have duplicate departments');
ELSE
dept_gtt_pkg.v_pk_tt(:new.deptno):=
dept_gtt_pkg.v_pk_tt(:old.deptno);
dept_gtt_pkg.v_pk_tt.delete(:old.deptno);
END IF;
END IF;
dept_gtt_pkg.v_dept_tt(dept_gtt_pkg.v_pk_tt(:new.deptno)):=
dept_gtt_ot(:new.deptno,:new.dname,:new.loc);
END IF;
END;
/
Solution (4)
79 of 90
SQL> INSERT INTO v_dept_gtt SELECT * FROM dept WHERE deptno in
(10,20);
2 rows created.
SQL> select * from v_dept_gtt;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
SQL> INSERT INTO v_dept_gtt(deptno,loc) VALUES (50,'NEW JERSEY');
1 row created.
SQL> UPDATE v_dept_gtt SET dname='DEV' WHERE deptno=50;
1 row updated.
SQL> DELETE FROM v_dept_gtt WHERE deptno=20;
1 row deleted.
SQL> SELECT * FROM v_dept_gtt;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
50 DEV NEW JERSEY
Proof of Functionality
80 of 90
Solution Impact
System impact:
 Significantly less log file switches needed
 No sudden slow-downs and hiccups.
 Higher memory utilization and CPU overhead
 Average response time increased from 0.25 seconds
to 0.3 seconds.
User impact:
 Much more predictable performance = happy users
81 of 90
Story #3: When to stop?
82 of 90
Dangers of Views
Views are definitions, not data
 Calling view multiple times = doing the same job
multiple times.
 There may be a moment when persisting query
results may be more efficient.
 Implementation of persistency depends upon your
requirements
 Materialized views (lots of options)
 Tables + manual refresh scripts
83 of 90
Real World Example
Existing solution:
 Reporting module is based on very complex views
 After corporate merge, data volume quadrupled
 Reports started to slow down.
Revised Solution:
 Core views became materialized with nightly full
refresh.
 Users gladly accepted daily data lag.
Advantage of using views from the beginning:
 Simple server-side change did the job!
84 of 90
Story #4: Views as Architectural Tools
85 of 90
Data Modeling Problem
ERD data model
 Can be perfectly implemented as tables+constraints
 Very limited
Class model
 Much better tool to describe the world
 Cannot be directly mapped to table structure
86 of 90
Solution
Class model:
 Table - perfectly relational
 Package - implements UML-related functionality
 View – presents class exactly as specified in class
model
87 of 90
Illustration (1)
 Abstract class:
88 of 90
Illustration (2)
 Generated view:
CREATE OR REPLACE VIEW person
AS
select
EMPLOYEE_OID PERSON_OID
,'Employee' PERSON_CD
,to_char(NameLast_TX||' '||NameFirst_TX) PERSON_DSP
,NAMEFIRST_TX NAMEFIRST_TX
,NAMELAST_TX NAMELAST_TX
from EMPLOYEE
union all
select
CONTACT_OID PERSON_OID
,'Contact' PERSON_CD
,to_char(NameLast_TX||' '||NameFirst_TX) PERSON_DSP
,NAMEFIRST_TX NAMEFIRST_TX
,NAMELAST_TX NAMELAST_TX
from CONTACT
89 of 90
Summary
Views are significantly more than just stored
queries
 ... because they are interfaces to the outside world
(and even Oracle agrees  ).
Effective utilization of the database is
impossible without deep knowledge of PL/SQL
 … since it is closer to your data than any other
language environment.
It is important to check for new (or forgotten)
features
 … because there are LOTS of them!
90 of 90
Contact Information
 Michael Rosenblum – mrosenblum@dulcian.com
 Dulcian, Inc. website - www.dulcian.com
 Blog: wonderingmisha.blogspot.com
Available NOW:
Oracle PL/SQL Performance
Tuning Tips & Techniques

More Related Content

What's hot

Performance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, HowPerformance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, How
Karen Morton
 
Flexviews materialized views for my sql
Flexviews materialized views for my sqlFlexviews materialized views for my sql
Flexviews materialized views for my sql
Justin Swanhart
 
Noinject
NoinjectNoinject
Noinject
Justin Swanhart
 
Database administration commands
Database administration commands Database administration commands
Database administration commands
Varsha Ajith
 
Oracle ORA Errors
Oracle ORA ErrorsOracle ORA Errors
Oracle ORA Errors
Manish Mudhliyar
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
Alex Zaballa
 
Summary tables with flexviews
Summary tables with flexviewsSummary tables with flexviews
Summary tables with flexviews
Justin Swanhart
 
Oracle PL/SQL Bulk binds
Oracle PL/SQL Bulk bindsOracle PL/SQL Bulk binds
Oracle PL/SQL Bulk binds
Scott Wesley
 
Oracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New FeaturesOracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New Features
Alex Zaballa
 
Meg bernal insight2014 4219
Meg bernal insight2014 4219Meg bernal insight2014 4219
Meg bernal insight2014 4219
Peter Schouboe
 
MySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web ApplicationsMySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web Applications
OSSCube
 
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321maclean liu
 
你所不知道的Oracle后台进程Smon功能
你所不知道的Oracle后台进程Smon功能你所不知道的Oracle后台进程Smon功能
你所不知道的Oracle后台进程Smon功能
maclean liu
 
EMCLI Crash Course - DOAG Germany
EMCLI Crash Course - DOAG GermanyEMCLI Crash Course - DOAG Germany
EMCLI Crash Course - DOAG Germany
Gokhan Atil
 
Oracle Data redaction - GUOB - OTN TOUR LA - 2015
Oracle Data redaction - GUOB - OTN TOUR LA - 2015Oracle Data redaction - GUOB - OTN TOUR LA - 2015
Oracle Data redaction - GUOB - OTN TOUR LA - 2015
Alex Zaballa
 
Bypass dbms assert
Bypass dbms assertBypass dbms assert
Bypass dbms assertfangjiafu
 
Oracle : Monitoring and Diagnostics without OEM
Oracle : Monitoring and Diagnostics without OEMOracle : Monitoring and Diagnostics without OEM
Oracle : Monitoring and Diagnostics without OEM
Hemant K Chitale
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
InSync Conference
 
10 Creating Triggers
10 Creating Triggers10 Creating Triggers
10 Creating Triggers
rehaniltifat
 

What's hot (20)

Performance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, HowPerformance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, How
 
Flexviews materialized views for my sql
Flexviews materialized views for my sqlFlexviews materialized views for my sql
Flexviews materialized views for my sql
 
Noinject
NoinjectNoinject
Noinject
 
Database administration commands
Database administration commands Database administration commands
Database administration commands
 
Oracle ORA Errors
Oracle ORA ErrorsOracle ORA Errors
Oracle ORA Errors
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
 
Stored procedure
Stored procedureStored procedure
Stored procedure
 
Summary tables with flexviews
Summary tables with flexviewsSummary tables with flexviews
Summary tables with flexviews
 
Oracle PL/SQL Bulk binds
Oracle PL/SQL Bulk bindsOracle PL/SQL Bulk binds
Oracle PL/SQL Bulk binds
 
Oracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New FeaturesOracle Database 12.1.0.2 New Features
Oracle Database 12.1.0.2 New Features
 
Meg bernal insight2014 4219
Meg bernal insight2014 4219Meg bernal insight2014 4219
Meg bernal insight2014 4219
 
MySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web ApplicationsMySQL Stored Procedures: Building High Performance Web Applications
MySQL Stored Procedures: Building High Performance Web Applications
 
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321
【Maclean liu技术分享】拨开oracle cbo优化器迷雾,探究histogram直方图之秘 0321
 
你所不知道的Oracle后台进程Smon功能
你所不知道的Oracle后台进程Smon功能你所不知道的Oracle后台进程Smon功能
你所不知道的Oracle后台进程Smon功能
 
EMCLI Crash Course - DOAG Germany
EMCLI Crash Course - DOAG GermanyEMCLI Crash Course - DOAG Germany
EMCLI Crash Course - DOAG Germany
 
Oracle Data redaction - GUOB - OTN TOUR LA - 2015
Oracle Data redaction - GUOB - OTN TOUR LA - 2015Oracle Data redaction - GUOB - OTN TOUR LA - 2015
Oracle Data redaction - GUOB - OTN TOUR LA - 2015
 
Bypass dbms assert
Bypass dbms assertBypass dbms assert
Bypass dbms assert
 
Oracle : Monitoring and Diagnostics without OEM
Oracle : Monitoring and Diagnostics without OEMOracle : Monitoring and Diagnostics without OEM
Oracle : Monitoring and Diagnostics without OEM
 
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
Tony jambu   (obscure) tools of the trade for tuning oracle sq lsTony jambu   (obscure) tools of the trade for tuning oracle sq ls
Tony jambu (obscure) tools of the trade for tuning oracle sq ls
 
10 Creating Triggers
10 Creating Triggers10 Creating Triggers
10 Creating Triggers
 

Similar to A New View of Database Views

Programming in Oracle with PL/SQL
Programming in Oracle with PL/SQLProgramming in Oracle with PL/SQL
Programming in Oracle with PL/SQL
lubna19
 
Oracle 11g new features for developers
Oracle 11g new features for developersOracle 11g new features for developers
Oracle 11g new features for developers
Scott Wesley
 
PL/SQL
PL/SQLPL/SQL
PL/SQL
Vaibhav0
 
Performance tuning
Performance tuningPerformance tuning
Performance tuning
ami111
 
Web Developer make the most out of your Database !
Web Developer make the most out of your Database !Web Developer make the most out of your Database !
Web Developer make the most out of your Database !
Jean-Marc Desvaux
 
Oracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional CompilationOracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional Compilation
Scott Wesley
 
Oracle APEX Performance
Oracle APEX PerformanceOracle APEX Performance
Oracle APEX Performance
Scott Wesley
 
Plsql coding conventions
Plsql coding conventionsPlsql coding conventions
Plsql coding conventions
Fang Yu
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
Alex Zaballa
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
Alex Zaballa
 
DOODB_LAB.pptx
DOODB_LAB.pptxDOODB_LAB.pptx
DOODB_LAB.pptx
FilestreamFilestream
 
Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09
Thuan Nguyen
 
Oracle trigger
Oracle triggerOracle trigger
Oracle trigger
nasrul28
 
Common Coding and Design mistakes (that really mess up performance)
Common Coding and Design mistakes (that really mess up performance)Common Coding and Design mistakes (that really mess up performance)
Common Coding and Design mistakes (that really mess up performance)
Sage Computing Services
 
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
Rainer Schuettengruber
 
Unit 3(rdbms)
Unit 3(rdbms)Unit 3(rdbms)
Unit 3(rdbms)Jay Patel
 
Unit 3(rdbms)
Unit 3(rdbms)Unit 3(rdbms)
Unit 3(rdbms)Jay Patel
 

Similar to A New View of Database Views (20)

Programming in Oracle with PL/SQL
Programming in Oracle with PL/SQLProgramming in Oracle with PL/SQL
Programming in Oracle with PL/SQL
 
Oracle 11g new features for developers
Oracle 11g new features for developersOracle 11g new features for developers
Oracle 11g new features for developers
 
PL/SQL
PL/SQLPL/SQL
PL/SQL
 
Performance tuning
Performance tuningPerformance tuning
Performance tuning
 
Oracle
OracleOracle
Oracle
 
Web Developer make the most out of your Database !
Web Developer make the most out of your Database !Web Developer make the most out of your Database !
Web Developer make the most out of your Database !
 
Oracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional CompilationOracle PL/SQL - Creative Conditional Compilation
Oracle PL/SQL - Creative Conditional Compilation
 
Oracle APEX Performance
Oracle APEX PerformanceOracle APEX Performance
Oracle APEX Performance
 
Plsql coding conventions
Plsql coding conventionsPlsql coding conventions
Plsql coding conventions
 
Introduction to mysql part 3
Introduction to mysql part 3Introduction to mysql part 3
Introduction to mysql part 3
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
 
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should KnowDBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
DBA Brasil 1.0 - DBA Commands and Concepts That Every Developer Should Know
 
DOODB_LAB.pptx
DOODB_LAB.pptxDOODB_LAB.pptx
DOODB_LAB.pptx
 
Unit 4
Unit 4Unit 4
Unit 4
 
Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09Oracle - Program with PL/SQL - Lession 09
Oracle - Program with PL/SQL - Lession 09
 
Oracle trigger
Oracle triggerOracle trigger
Oracle trigger
 
Common Coding and Design mistakes (that really mess up performance)
Common Coding and Design mistakes (that really mess up performance)Common Coding and Design mistakes (that really mess up performance)
Common Coding and Design mistakes (that really mess up performance)
 
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
2018 db-rainer schuettengruber-beating-oracles_optimizer_at_its_own_game-pres...
 
Unit 3(rdbms)
Unit 3(rdbms)Unit 3(rdbms)
Unit 3(rdbms)
 
Unit 3(rdbms)
Unit 3(rdbms)Unit 3(rdbms)
Unit 3(rdbms)
 

Recently uploaded

Eureka, I found it! - Special Libraries Association 2021 Presentation
Eureka, I found it! - Special Libraries Association 2021 PresentationEureka, I found it! - Special Libraries Association 2021 Presentation
Eureka, I found it! - Special Libraries Association 2021 Presentation
Access Innovations, Inc.
 
Media as a Mind Controlling Strategy In Old and Modern Era
Media as a Mind Controlling Strategy In Old and Modern EraMedia as a Mind Controlling Strategy In Old and Modern Era
Media as a Mind Controlling Strategy In Old and Modern Era
faizulhassanfaiz1670
 
Bitcoin Lightning wallet and tic-tac-toe game XOXO
Bitcoin Lightning wallet and tic-tac-toe game XOXOBitcoin Lightning wallet and tic-tac-toe game XOXO
Bitcoin Lightning wallet and tic-tac-toe game XOXO
Matjaž Lipuš
 
Obesity causes and management and associated medical conditions
Obesity causes and management and associated medical conditionsObesity causes and management and associated medical conditions
Obesity causes and management and associated medical conditions
Faculty of Medicine And Health Sciences
 
International Workshop on Artificial Intelligence in Software Testing
International Workshop on Artificial Intelligence in Software TestingInternational Workshop on Artificial Intelligence in Software Testing
International Workshop on Artificial Intelligence in Software Testing
Sebastiano Panichella
 
Doctoral Symposium at the 17th IEEE International Conference on Software Test...
Doctoral Symposium at the 17th IEEE International Conference on Software Test...Doctoral Symposium at the 17th IEEE International Conference on Software Test...
Doctoral Symposium at the 17th IEEE International Conference on Software Test...
Sebastiano Panichella
 
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
Orkestra
 
0x01 - Newton's Third Law: Static vs. Dynamic Abusers
0x01 - Newton's Third Law:  Static vs. Dynamic Abusers0x01 - Newton's Third Law:  Static vs. Dynamic Abusers
0x01 - Newton's Third Law: Static vs. Dynamic Abusers
OWASP Beja
 
Announcement of 18th IEEE International Conference on Software Testing, Verif...
Announcement of 18th IEEE International Conference on Software Testing, Verif...Announcement of 18th IEEE International Conference on Software Testing, Verif...
Announcement of 18th IEEE International Conference on Software Testing, Verif...
Sebastiano Panichella
 
somanykidsbutsofewfathers-140705000023-phpapp02.pptx
somanykidsbutsofewfathers-140705000023-phpapp02.pptxsomanykidsbutsofewfathers-140705000023-phpapp02.pptx
somanykidsbutsofewfathers-140705000023-phpapp02.pptx
Howard Spence
 
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
OECD Directorate for Financial and Enterprise Affairs
 
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdfBonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
khadija278284
 
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdfSupercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
Access Innovations, Inc.
 
Getting started with Amazon Bedrock Studio and Control Tower
Getting started with Amazon Bedrock Studio and Control TowerGetting started with Amazon Bedrock Studio and Control Tower
Getting started with Amazon Bedrock Studio and Control Tower
Vladimir Samoylov
 
María Carolina Martínez - eCommerce Day Colombia 2024
María Carolina Martínez - eCommerce Day Colombia 2024María Carolina Martínez - eCommerce Day Colombia 2024
María Carolina Martínez - eCommerce Day Colombia 2024
eCommerce Institute
 
Acorn Recovery: Restore IT infra within minutes
Acorn Recovery: Restore IT infra within minutesAcorn Recovery: Restore IT infra within minutes
Acorn Recovery: Restore IT infra within minutes
IP ServerOne
 

Recently uploaded (16)

Eureka, I found it! - Special Libraries Association 2021 Presentation
Eureka, I found it! - Special Libraries Association 2021 PresentationEureka, I found it! - Special Libraries Association 2021 Presentation
Eureka, I found it! - Special Libraries Association 2021 Presentation
 
Media as a Mind Controlling Strategy In Old and Modern Era
Media as a Mind Controlling Strategy In Old and Modern EraMedia as a Mind Controlling Strategy In Old and Modern Era
Media as a Mind Controlling Strategy In Old and Modern Era
 
Bitcoin Lightning wallet and tic-tac-toe game XOXO
Bitcoin Lightning wallet and tic-tac-toe game XOXOBitcoin Lightning wallet and tic-tac-toe game XOXO
Bitcoin Lightning wallet and tic-tac-toe game XOXO
 
Obesity causes and management and associated medical conditions
Obesity causes and management and associated medical conditionsObesity causes and management and associated medical conditions
Obesity causes and management and associated medical conditions
 
International Workshop on Artificial Intelligence in Software Testing
International Workshop on Artificial Intelligence in Software TestingInternational Workshop on Artificial Intelligence in Software Testing
International Workshop on Artificial Intelligence in Software Testing
 
Doctoral Symposium at the 17th IEEE International Conference on Software Test...
Doctoral Symposium at the 17th IEEE International Conference on Software Test...Doctoral Symposium at the 17th IEEE International Conference on Software Test...
Doctoral Symposium at the 17th IEEE International Conference on Software Test...
 
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
Sharpen existing tools or get a new toolbox? Contemporary cluster initiatives...
 
0x01 - Newton's Third Law: Static vs. Dynamic Abusers
0x01 - Newton's Third Law:  Static vs. Dynamic Abusers0x01 - Newton's Third Law:  Static vs. Dynamic Abusers
0x01 - Newton's Third Law: Static vs. Dynamic Abusers
 
Announcement of 18th IEEE International Conference on Software Testing, Verif...
Announcement of 18th IEEE International Conference on Software Testing, Verif...Announcement of 18th IEEE International Conference on Software Testing, Verif...
Announcement of 18th IEEE International Conference on Software Testing, Verif...
 
somanykidsbutsofewfathers-140705000023-phpapp02.pptx
somanykidsbutsofewfathers-140705000023-phpapp02.pptxsomanykidsbutsofewfathers-140705000023-phpapp02.pptx
somanykidsbutsofewfathers-140705000023-phpapp02.pptx
 
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
Competition and Regulation in Professional Services – KLEINER – June 2024 OEC...
 
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdfBonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
Bonzo subscription_hjjjjjjjj5hhhhhhh_2024.pdf
 
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdfSupercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
Supercharge your AI - SSP Industry Breakout Session 2024-v2_1.pdf
 
Getting started with Amazon Bedrock Studio and Control Tower
Getting started with Amazon Bedrock Studio and Control TowerGetting started with Amazon Bedrock Studio and Control Tower
Getting started with Amazon Bedrock Studio and Control Tower
 
María Carolina Martínez - eCommerce Day Colombia 2024
María Carolina Martínez - eCommerce Day Colombia 2024María Carolina Martínez - eCommerce Day Colombia 2024
María Carolina Martínez - eCommerce Day Colombia 2024
 
Acorn Recovery: Restore IT infra within minutes
Acorn Recovery: Restore IT infra within minutesAcorn Recovery: Restore IT infra within minutes
Acorn Recovery: Restore IT infra within minutes
 

A New View of Database Views

  • 1. 1 of 90 #458: A New View of Database Views Michael Rosenblum Dulcian, Inc. www.dulcian.com
  • 2. 2 of 90 Who Am I? – “Misha”  Oracle ACE  Co-author of 3 books  PL/SQL for Dummies  Expert PL/SQL Practices  Oracle PL/SQL Performance Tuning Tips & Techniques (Rosenblum & Dorsey, Oracle Press, July 2014)  Won ODTUG 2009 Speaker of the Year  Known for:  SQL and PL/SQL tuning  Complex functionality  Code generators  Repository-based development
  • 3. 3 of 90 Views??? Common train of thought:  Stored SQL queries  Nothing to worry about  Reasonably transparent and stackable  Minimal impact  Have been around forever…..  (Usually implies)…and have never changed.
  • 4. 4 of 90 Views!!! “Thick database” approach:  Views can serve as an isolation layer  UI should never talk to tables!  Views can be easily changed.  Views are editionable (EBR).  Isolation can be bi-directional.  Views are complex.  Lots of new functionality in every version  Can impact Cost Based Optimizer (CBO) decisions  Side-effects and non-trivial impact
  • 5. 5 of 90 Outline To be discussed:  De-normalized views with INSTEAD OF triggers  Function-based views  Special cases:  Compound triggers  Cross-edition views  Various performance considerations  Will not be discussed:  Object views  Materialized views
  • 6. 6 of 90 Views: Functionality & Features
  • 7. 7 of 90 The Idea View is (IMHO!):  Data set, broadly defined at design-time and formed at run-time.  The definition may mutate via:  Parameterized conditions  Dynamic SQL  This data set may accept DMLs  Only on a per-row basis (no statement-level actions)  Directly or via associated PL/SQL program units  Set is not persistent and may need to be rebuilt to accept DMLs.
  • 8. 8 of 90 The Reasoning Logical denormalization is great:  Less coding in the UI  Transparent system design  Long-term protection against data model changes  Simplified testing
  • 10. 10 of 90 create or replace view scott.v_emp as select e.empno, e.ename, e.deptno, d.dname, e.sal from scott.emp e, scott.dept d where e.deptno=d.deptno Basic Code 
  • 11. 11 of 90 select * from dba_updatable_columns where table_name = 'V_EMP' COLUMN_NAME UPDATABLE INSERTABLE DELETABLE --------------- --------------- ------------- --------- EMPNO YES YES YES ENAME YES YES YES DEPTNO YES YES YES DNAME NO NO NO SAL YES YES YES Direct DML…Sometimes
  • 12. 12 of 90 create or replace trigger scott.v_emp_iu instead of update on scott.v_emp begin if :new.sal!=:old.sal then if sys_context ('userenv','CLIENT_INFO')='SalMaint' then update emp set sal = :new.sal where empno = :old.empno; else raise_application_error (-20001,'Not enough privileges'); end if; else update emp set ename = :new.ename where empno = :old.empno; end if; end; INSTEAD-OF – Functionality
  • 13. 13 of 90 exec scott.runStats_pkg.rs_start; alter trigger scott.v_emp_iu disable; begin for i in 1..10000 loop update scott.v_emp set ename=ename where empno = 7782; end loop; end; / exec scott.runStats_pkg.rs_middle; alter trigger scott.v_emp_iu enable; begin for i in 1..10000 loop update scott.v_emp set ename=ename where empno = 7782; end loop; end; / exec scott.runStats_pkg.rs_stop; Run1 ran in 35 cpu hsecs Run2 ran in 77 cpu hsecs run 1 ran in 45.45% of the time Name Run1 Run2 Diff STAT...CPU used by this session 36 79 43 STAT...execute count 10,037 20,036 9,999 STAT...session logical reads 40,441 50,480 10,039 INSTEAD-OF – Extra Cost What???
  • 14. 14 of 90 DMLs Against Views
  • 15. 15 of 90 DML Implementation UPDATE on view = SELECT + UPDATE DELETE on view = SELECT + DELETE INSERT on view = Only INSERT
  • 16. 16 of 90 Test Case (1) CREATE TYPE test_tab_ot AS OBJECT (owner_tx VARCHAR2(30), name_tx VARCHAR2(30), object_id NUMBER, type_tx VARCHAR2(30)); CREATE TYPE test_tab_nt IS TABLE OF test_tab_ot; CREATE FUNCTION f_searchTestTab_tt (i_type_tx VARCHAR2) RETURN test_tab_nt IS v_out_tt test_tab_nt; begin SELECT test_tab_ot(owner, object_name, object_id, object_type) BULK COLLECT INTO v_out_tt FROM test_tab WHERE object_type = i_type_tx; dbms_output.put_line('Inside f_searchTestTab_tt:'||v_out_tt.count); RETURN v_out_tt; END;
  • 17. 17 of 90 Test Case (2) create or replace view v_search_table as select * from table(f_searchtesttab_tt('TABLE')); create or replace trigger v_search_table_iiud instead of insert or update or delete on v_search_table begin if inserting then dbms_output.put_line('Insert'); elsif updating then dbms_output.put_line('Update'); elsif deleting then dbms_output.put_line(‘Delete'); end if; end;
  • 18. 18 of 90 DML Check SQL> INSERT INTO v_search_table (object_id, name_tx) 2 VALUES (-1,'A'); Insert 1 row created. SQL> UPDATE v_search_table SET name_tx = 'Test‘ 2 WHERE object_id = 5; Inside f_searchTestTab_tt:1571 Update 1 row updated. SQL> DELETE FROM v_search_table WHERE object_id = 5; Inside f_searchTestTab_tt:1571 Delete 1 row deleted. Function is not fired! Process all to update one?
  • 19. 19 of 90 Important! To fire INSTEAD OF UPDATE/DELETE, Oracle must locate row first. Oracle must have the whole resulting set available to filter it  … but you can cheat 
  • 20. 20 of 90 Parameterized View (1) CREATE PACKAGE global_pkg IS v_object_id NUMBER; END; CREATE FUNCTION f_searchTestTab_tt (i_type_tx varchar2) RETURN test_tab_nt is v_out_tt test_tab_nt; BEGIN IF global_pkg.v_object_id IS NULL THEN SELECT test_tab_ot(owner, object_name, object_id, object_type) BULK COLLECT INTO v_out_tt FROM test_tab WHERE object_type = i_type_tx; ELSE SELECT test_tab_ot(owner, object_name, object_id, object_type) BULK COLLECT INTO v_out_tt FROM test_tab WHERE object_id = global_pkg.v_object_id; END IF; dbms_output.put_line ('Inside f_searchTestTab_tt:'||v_out_tt.count); RETURN v_out_tt; END; Usage (if needed) Global parameter
  • 21. 21 of 90 Parameterized View (2) SQL> BEGIN global_pkg.v_object_id:=5; END; 2 / SQL> UPDATE v_search_table SET name_tx = 'Test' 2 WHERE object_id = 5; Inside f_searchTestTab_tt:1 Update 1 row updated. SQL> DELETE FROM v_search_table WHERE object_id = 5; Inside f_searchTestTab_tt:1 Delete 1 row deleted.
  • 22. 22 of 90 Parameterized View (3) SQL> exec runstats_pkg.rs_start; SQL> BEGIN 2 global_pkg.v_object_id:=NULL; 3 FOR i IN 1..100 LOOP 4 UPDATE v_search_table SET name_tx = 'Test'||i 5 WHERE object_id = 5; 6 END LOOP; 7 END; 8 / SQL> exec runstats_pkg.rs_middle; SQL> BEGIN 2 global_pkg.v_object_id:=5; 3 FOR i IN 1..100 LOOP 4 UPDATE v_search_table SET name_tx = 'Test'||i 5 WHERE object_id = 5; 6 END LOOP; 7 END; 8 / SQL> exec runstats_pkg.rs_stop; Run1 ran in 181 cpu hsecs Run2 ran in 28 cpu hsecs run 1 ran in 646.43% of the time 5x improvement
  • 23. 23 of 90 Compound Triggers on Views
  • 24. 24 of 90 Alternative to INSTEAD OF You can also create a COMPOUND trigger instead of an INSTEAD OF trigger   Trigger with common program area Impact  Pro:  Common program area – possible to share code and global variables  simulating statement-level BEFORE event (sorry, there is no way to simulate an AFTER event)  Con:  Not very stable in 11g
  • 25. 25 of 90 CREATE OR REPLACE PACKAGE counter_pkg IS v_nr NUMBER:=0; PROCEDURE p_check; procedure p_up; END; CREATE OR REPLACE PACKAGE BODY counter_pkg IS PROCEDURE p_check is BEGIN dbms_output.put_line('Fired:'||counter_pkg.v_nr); counter_pkg.v_nr:=0; END; procedure p_up is begin counter_pkg.v_nr:=counter_pkg.v_nr+1; end; END; create or replace function f_securityCheck_yn return varchar2 is begin counter_pkg.p_up; if sys_context ('USERENV', 'CLIENT_INFO') ='SalMaint' then return 'Y'; else return 'N'; end if; end; create function f_change_nr (i_nr number) return number is begin counter_pkg.p_up; return i_nr+1; end; Monitoring tool
  • 26. 26 of 90 CREATE OR REPLACE TRIGGER v_search_table_IIUD INSTEAD OF INSERT OR UPDATE OR DELETE ON v_search_table BEGIN if f_securityCheck_yn = 'Y' then IF INSERTING THEN dbms_output.put_line('Insert'); ELSIF UPDATING THEN dbms_output.put_line('Update'); ELSIF DELETING THEN dbms_output.put_line('Delete'); END IF; end if; END; create or replace trigger v_search_table_IIUD_comp for insert or update or delete on v_search_table COMPOUND TRIGGER v_check_yn varchar2(1); instead of each row is begin if v_check_yn is null then v_check_yn:=f_securityCheck_yn; end if; if v_check_yn = 'Y' then IF INSERTING THEN dbms_output.put_line('Insert'); ELSIF UPDATING THEN dbms_output.put_line('Update'); ELSIF DELETING THEN dbms_output.put_line('Delete'); END IF; end if; end instead of each row; end; Performance impact (1) Common area
  • 27. 27 of 90 SQL> alter trigger v_search_table_IIUD_COMP disable; SQL> alter trigger v_search_table_IIUD enable; SQL> update v_search_table set name_tx = 'Test'; Inside f_searchTestTab_tt:1571 1571 rows updated. SQL> exec counter_pkg.p_check; Fired:1571 SQL> alter trigger v_search_table_IIUD_COMP enable; SQL> alter trigger v_search_table_IIUD disable; SQL> update v_search_table set name_tx = 'Test'; Inside f_searchTestTab_tt:1571 1571 rows updated. SQL> exec counter_pkg.p_check; Fired:1 SQL> exec dbms_application_info.set_client_info('SalMaint'); SQL> update v_search_table set name_tx = 'Test'; Inside f_searchTestTab_tt:1571 Update Update .... 1571 rows updated. SQL> exec counter_pkg.p_check; Fired:1 Performance impact (2) Only one call!
  • 28. 28 of 90 Dangers of Logical Primary Keys
  • 29. 29 of 90 The Real Story Synthetic primary keys on views  Sometimes required by front-end environments (to uniquely identify the row in the cache)  Extremely dangerous if blindly used for INSERT/UPDATE/DELETE
  • 30. 30 of 90 Test Case CREATE OR REPLACE VIEW v_test_tab AS SELECT 'Main|'||object_id pk_tx, a.* FROM test_tab_main a UNION ALL SELECT 'Other|'||object_id pk_tx, a.* FROM test_tab_other a;
  • 31. 31 of 90 Performance Impact SQL> set autotrace traceonly explain SQL> UPDATE v_test_tab 2 SET object_name='Test' 3 WHERE pk_tx='Main|1'; 1 row updated. Execution Plan ---------------------------------------------------------- Plan hash value: 3568876726 ------------------------------------------------------------------------- |Id| Operation | Name | Rows | Bytes | Cost (%CPU)| ------------------------------------------------------------------------- | 0| UPDATE STATEMENT | | 500 | 45500 | 236 (1)| | 1| UPDATE | V_TEST_TAB | | | | | 2| VIEW | V_TEST_TAB | 500 | 45500 | 236 (1)| | 3| UNION-ALL | | | | | |*4| TABLE ACCESS FULL| TEST_TAB_MAIN | 15 | 330 | 9 (0)| |*5| TABLE ACCESS FULL| TEST_TAB_OTHER | 485 | 14550 | 227 (1)| --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - filter('Main|'||TO_CHAR("OBJECT_ID")='Main|1') 5 - filter('Other|'||TO_CHAR("OBJECT_ID")='Main|1') Full-table scans!
  • 32. 32 of 90 Optimization of UPDATEs
  • 33. 33 of 90 Resource Issues Problem  INSTEAD-OF UPDATE triggers often reference all columns of the underlying tables  … instead of trying to figure out what has been changed.  UNDO is generated for all columns mentioned in the UPDATE statement  … regardless of whether they were changed or not  … which causes major I/O overhead. Alternative:  Use Dynamic SQL to modify only changed columns  … i.e. trade CPU utilization for better I/O!
  • 34. 34 of 90 Regular Trigger create or replace trigger v_test_tab_iu instead of update on v_test_tab begin if :new.object_type=‘TABLE' then update test_tab_main set owner=:new.owner, object_name=:new.object_name, subobject_name=:new.subobject_name, object_type=:new.object_type, created=:new.created, last_ddl_time=:new.last_ddl_time, timestamp=:new.timestamp, status=:new.status, temporary=:new.temporary, generated=:new.generated, secondary=:new.secondary, namespace=:new.namespace, edition_name=:new.edition_name, sharing=:new.sharing, editionable=:new.editionable, oracle_maintained=:new.oracle_maintained where object_id=:old.object_id; else update test_tab_other set << the same list of columns as above >> where object_id=:old.object_id; end if; end;
  • 35. 35 of 90 Dynamic SQL Trigger (1) create or replace trigger v_test_tab_dynamic_iu instead of update on v_test_tab declare v_main_rec test_tab_main%rowtype; v_mainupdate_tx varchar2(32767); v_other_rec test_tab_other%rowtype; v_otherupdate_tx varchar2(32767); begin if :new.object_type='table' then -- compare old/new for each attribute if :old.object_name is null and :new.object_name is not null or :old.object_name is not null and :new.object_name is null or :old.object_name!=:new.object_name then v_main_rec.object_name:=:new.object_name; v_mainupdate_tx:=v_mainupdate_tx|| case when v_mainupdate_tx is not null then ',' else null end||chr(10)|| ' object_name=v_rec.object_name'; end if; ... Store new value (if changed)
  • 36. 36 of 90 Dynamic SQL Trigger (2) v_main_rec.object_id:=:old.object_id; v_mainupdate_tx:= 'declare '||chr(10)|| ' v_rec test_tab_main%rowtype:=:1;'||chr(10)|| 'begin '||chr(10)|| ' update test_tab_main ' ||chr(10)|| ' set '||v_mainupdate_tx||chr(10)|| ' where object_id=v_rec.object_id;'||chr(10)|| 'end;'; execute immediate v_mainupdate_tx using v_main_rec; else << the same logic as above for test_tab_other >> end if; end;
  • 37. 37 of 90 Performance Tradeoff SQL> exec runstats_pkg.rs_start; << enable Dynamic trigger>> SQL> begin 2 for i in 1..10000 loop 3 UPDATE v_test_tab SET object_name='Test'||i WHERE object_id = 5; 4 end loop; 5 END; 6 / SQL> exec runstats_pkg.rs_middle; << enable regular trigger and rerun the same logic>> SQL> exec runstats_pkg.rs_stop; Run1 ran in 390 cpu hsecs Run2 ran in 496 cpu hsecs run 1 ran in 78.63% of the time Name Run1 Run2 Diff STAT...recursive calls 20,329 30,244 9,915 STAT...execute count 20,102 30,095 9,993 STAT...undo change vector size 2,495,476 938,552 -1,556,924 STAT...redo size 5,820,096 2,772,332 -3,047,764 Run1 latches total versus runs -- difference and pct Run1 Run2 Diff Pct 136,486 184,679 48,193 73.90% More CPU time Much less I/O
  • 38. 38 of 90 PL/SQL Functions and Views
  • 39. 39 of 90 Setup  Functions can be used as columns in views: CREATE FUNCTION f_isEastCoast_yn (i_deptno NUMBER) RETURN VARCHAR2 IS v_out_yn varchar2(1); BEGIN SELECT CASE WHEN loc IN ('NEW YORK', 'BOSTON') THEN 'Y' ELSE 'N' END INTO v_out_yn FROM dept WHERE deptno = i_deptno; RETURN v_out_yn; END; CREATE VIEW v_emp_loc AS SELECT emp.empno, emp.ename, emp.deptno, f_isEastCoast_yn(deptno) eastCoast_yn FROM emp; Returns Y/N
  • 40. 40 of 90 Problem Default behavior: SQL> SELECT column_name, data_type, data_length 2 FROM user_tab_columns 3 WHERE table_name = 'V_EMP_LOC' 4 ORDER by column_id; COLUMN_NAME DATA_TYPE DATA_LENGTH --------------- --------------- ----------- EMPNO NUMBER 22 ENAME VARCHAR2 10 DEPTNO NUMBER 22 EASTCOAST_YN VARCHAR2 4000 Over-allocation can impact front-end and middle-tier that may read the Oracle Data Dictionary. In the case of materialized views – storage over-allocation
  • 41. 41 of 90 Solution CREATE OR REPLACE VIEW v_emp_loc AS SELECT emp.empno, emp.ename, emp.deptno, cast(f_isEastCoast_yn(deptno) as VARCHAR2(1)) eastCoast_yn FROM emp SQL> SELECT column_name, data_type, data_length 2 FROM user_tab_columns 3 WHERE table_name = 'V_EMP_LOC' 4 ORDER by column_id; COLUMN_NAME DATA_TYPE DATA_LENGTH --------------- --------------- ----------- EMPNO NUMBER 22 ENAME VARCHAR2 10 DEPTNO NUMBER 22 EASTCOAST_YN VARCHAR2 1 Exact allocation
  • 42. 42 of 90 Views and ORDER BY Danger
  • 43. 43 of 90 SELECT and ORDER BY (1)  Output: SQL> SELECT empno, ename, f_change_nr(empno) change_nr 2 FROM emp WHERE deptno = 20 3 ORDER BY 3; 5 rows selected. SQL> exec counter_pkg.p_check; Fired: ? SQL> SELECT empno, change_nr 2 FROM (SELECT empno, ename, f_change_nr(empno) change 3 FROM emp WHERE deptno = 20 4 ORDER BY 3); 5 rows selected. SQL> exec counter_pkg.p_check; Fired: ? In-line view causes double-firing 5 10  Problem:  Why does the inline view cause a double fire?
  • 44. 44 of 90 SELECT and ORDER BY (2)  Research of 10053 trace: Order-by elimination (OBYE) *************************** OBYE: OBYE performed. OBYE: OBYE bypassed: no order by to eliminate. Final query after transformations:*** UNPARSED QUERY IS *** SELECT "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME", "SCOTT"."F_CHANGE_NR"("EMP"."EMPNO") "CHANGE_NR" FROM "SCOTT"."EMP" "EMP" WHERE "EMP"."DEPTNO"=20 ORDER BY "SCOTT"."F_CHANGE_NR"("EMP"."EMPNO")  Explanation:  ORDER BY elimination is fired before the query transformation.  It does not find an ORDER BY clause in the root SELECT and stops.  After query transformation, ORDER BY suddenly appears.  It is not removed now.
  • 45. 45 of 90 SELECT and ORDER BY (3)  /*+ NO_MERGE */ hint solves the problem: SQL> select empno, change_nr 2 from (select /*+ no_merge */ 3 empno, ename, f_change_nr(empno) change_nr 4 from emp where deptno = 20 order by 3); 5 rows selected. SQL> exec counter_pkg.p_check; Fired: ?  Why bother? Because of real views: SQL> create or replace view v_emp as 2 select empno, ename, f_change_nr(empno) change_nr 3 from emp where deptno = 20 4 order by 3; view created. SQL> select empno, change_nr from v_emp; 5 rows selected. SQL> exec counter_pkg.p_check; Fired: ? Query rewrite is skipped.  ORDER BY elimination is applied directly. Same effect as in-line view 5 10
  • 46. 46 of 90 Important! ORDER BY clauses in views should be used very cautiously and preferably avoided altogether  … because the CBO is still not magic.
  • 47. 47 of 90 Hints and Views
  • 48. 48 of 90 Problem Yes, there are cases when hints are needed. Hints are easy to add if you have a single-level query. If you are using views:  Straightforward if you are lucky and can change underlying views.   Doable otherwise, but may be tricky.
  • 49. 49 of 90 Solution #1  Explicit naming of SELECT statements (20 char limit): create or replace view scott.v_emp as select /*+ QB_NAME(V_EMP_Main) */ e.empno, e.ename, e.deptno, d.dname, e.sal from scott.emp e, scott.dept d where e.deptno=d.deptno
  • 50. 50 of 90 Solution #1 - Proof SQL> select /*+ FULL(@V_EMP_Main e) */ * 2 from v_emp 3 where empno=7369; EMPNO ENAME DEPTNO DNAME SAL ---------- ---------- ---------- -------------- ---------- 7369 SMITH 20 RESEARCH 800 Execution Plan ---------------------------------------------------------- Plan hash value: 3625962092 ---------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | ---------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 30 | | 1 | NESTED LOOPS | | 1 | 30 | | 2 | NESTED LOOPS | | 1 | 30 | |* 3 | TABLE ACCESS FULL | EMP | 1 | 17 | |* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | | 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | ----------------------------------------------------------------
  • 51. 51 of 90 Solution #2  Find Oracle-generated object alias: SQL> explain plan for select * from v_emp where empno=7369; Explained. SQL> select * from table(dbms_xplan.display(null,null,'All')); ---------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | ---------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 30 | | 1 | NESTED LOOPS | | 1 | 30 | | 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 17 | |* 3 | INDEX UNIQUE SCAN | PK_EMP | 1 | | | 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | |* 5 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$F5BB74E1 2 - SEL$F5BB74E1 / E@SEL$2 3 - SEL$F5BB74E1 / E@SEL$2 4 - SEL$F5BB74E1 / D@SEL$2 5 - SEL$F5BB74E1 / D@SEL$2 Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("E"."EMPNO"=7369) 5 - access("E"."DEPTNO"="D"."DEPTNO")
  • 52. 52 of 90 Solution #2 - Proof SQL> select /*+ FULL(@SEL$2 e) */ * 2 from v_emp 3 where empno=7369; EMPNO ENAME DEPTNO DNAME SAL ---------- ---------- ---------- -------------- ---------- 7369 SMITH 20 RESEARCH 800 Execution Plan ---------------------------------------------------------- Plan hash value: 3625962092 ---------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | ---------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 30 | | 1 | NESTED LOOPS | | 1 | 30 | | 2 | NESTED LOOPS | | 1 | 30 | |* 3 | TABLE ACCESS FULL | EMP | 1 | 17 | |* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | | 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | ----------------------------------------------------------------
  • 53. 53 of 90 Keep in mind… Naming all subqueries costs you nothing, but makes production support much easier. Warnings:  Names may be ignored:  If two or more query blocks have the same name  If the same query block is hinted twice with different name  Beware of query transformation!
  • 55. 55 of 90 Concept Editioning view (Edition-Based Redefition):  Can be created only for edition-enabled users  Can have multiple versions  Lots of restrictions (no joins, conditions, grouping etc.) ~ more or less a synonym to the table -- Parent Edition create or replace editioning view scott.v_emp_ed as select empno, ename, hiredate from scott.emp; -- Child Edition (new column TIMESTAMP instead of DATE) create or replace editioning view scott.v_emp_ed as select empno, ename, hiredate_ts from scott.emp;
  • 56. 56 of 90 New Functionality  Editioning views may have the same triggers as tables -- Child edition: only new data create or replace trigger v_emp_ed_bu before update on v_emp_ed for each row Begin if :new.hiredate_ts <= to_timestamp('20150101','YYYYMMDD') then raise_application_error(-20001,'Data is too old'); end if; end; -- Parent edition: only old data create or replace trigger v_emp_ed_bu before update on v_emp_ed for each row Begin if :new.hiredate > to_date('20150101','YYYYMMDD') then raise_application_error(-20001,'Data is too new'); end if; end;
  • 58. 58 of 90 Views Multiple triggers of the same type:  FOLLOWS <trigger> clause Triggers can be created in DISABLED state. Create invalid view (for later recompilation):  FORCE clause
  • 59. 59 of 90 Views with Constraints (1)  Making view non-updatable  WITH READ ONLY clause create or replace view scott.v_emp as select e.empno,e.ename, e.deptno, d.dname, e.sal from scott.emp e, scott.dept d where e.deptno=d.deptno with read only constraint V_EMP_RO SQL> select constraint_name, constraint_type, table_name 2 from user_constraints 3 where table_name = 'V_EMP'; CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME ----------------- --------------- --------------------- V_EMP_RO O V_EMP
  • 60. 60 of 90 Views with Constraints (2)  WITH CHECK OPTION clause ~ Check constraint  Insert/Update for single-table views  Update is validated for multi-table views  Insert causes “ORA-01733: virtual column not allowed here”  Delete blocked if you have self-join create or replace view scott.v_emp as select e.empno, e.ename, e.deptno, d.dname, e.sal from scott.emp e, scott.dept d where e.deptno=d.deptno and d.deptno !=30 with check option constraint V_EMP_C SQL> select constraint_name, constraint_type, table_name 2 from user_constraints 3 where table_name = 'V_EMP'; CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION ----------------- --------------- ---------- ---------------- V_EMP_C V V_EMP NULL You cannot see condition 
  • 61. 61 of 90 Views with Constraints (3)  Primary/Unique key – documentation/CBO only create or replace view scott.v_emp ( empno, ename, deptno, dname, sal, constraint v_emp_pk primary key(empno) rely disable novalidate, constraint v_emp_uk unique (ename) rely disable novalidate ) as select e.empno, e.ename, e.deptno, d.dname, e.sal from scott.emp e, scott.dept d where e.deptno=d.deptno
  • 62. 62 of 90 SQL Text Expansion (1) Problem:  Views can be based on views that can be based on views …  How can you read what is really accessed? Solution (12c-only)  DBMS_UTILITY.EXPAND_SQL_TEXT
  • 63. 63 of 90 SQL Text Expansion (2) SQL> declare 2 v_tx varchar2(32767); 3 begin 4 dbms_utility.expand_sql_text 5 ('select * from scott.v_emp', v_tx); 6 dbms_output.put_line(v_tx); 7 end; 8 / SELECT "A1"."EMPNO" "EMPNO","A1"."ENAME" "ENAME","A1"."DEPTNO" "DEPTNO","A1"."DNAME" "DNAME","A1"."SAL" "SAL" FROM (SELECT "A3"."EMPNO" "EMPNO","A3"."ENAME" "ENAME","A3"."DEPTNO" "DEPTNO","A2"."DNAME" "DNAME","A3"."SAL" "SAL" FROM "SCOTT"."EMP" "A3","SCOTT"."DEPT" "A2" WHERE "A3"."DEPTNO"="A2"."DEPTNO" AND "A3"."EMPNO"<>30) "A1"
  • 64. 64 of 90 Real Business Cases
  • 65. 65 of 90 Storytelling #1 Views and front-end #2: Views as logical isolation #3: When to stop #4: Views as architectural tools
  • 66. 66 of 90 Story #1: Views and Front-End
  • 67. 67 of 90 How to Talk to Front-End Developers Problem:  How to explain the importance of views to front-end developers? Solution:  Explain the idea of roundtrip minimization!
  • 68. 68 of 90 Practical Aspects (1) Existing implementations:  Multiple separate requests to populate the screen  Total number of roundtrips sometimes in thousands for a single screen  Each request is cheap.  Total cost on all levels (DB/network/app server) is huge.
  • 69. 69 of 90 Web Application Architecture 3. Application Server 2. Send data from Client to app server 5. Database 6. Return Data from database to app server 1. Client 4. Send data from app server to database 7. Data in Application Server 8. Return data from app server to client 9. Data in client
  • 70. 70 of 90 Practical Aspects (2) Alternative:  A view where 1 row gets all data to populate one screen  1 round-trip  Since not a lot of data is being returned, the complexity of such a view can be pretty high.  Very often, you trade off higher memory utilization for less network requests.
  • 71. 71 of 90 Web Application Architecture 3. Application Server 2. Send data from Client to app server 5. Database 6. Return Data from DB to app server 1. Client 4. Send data from app server to DB 7. Data in Application Server 8. Return data from app server to client 9. Data in client Data UI views
  • 72. 72 of 90 Story #2: Views as Logical Isolation
  • 73. 73 of 90 History Existing system:  Major part of the solution requires data transformation via global temporary tables (session-level)  Significant scaling (from 150 to 2500 users) Impact:  Numerous log file switches  significant performance impact  LogMiner shows that ~ 75% of DMLs are related to GTT!
  • 74. 74 of 90 New Knowledge Session-level GTTs are subject to transaction activities  Even though there is no COMMIT, there is a ROLLBACK:  INSERT  Very little UNDO is generated: It is enough to generate the DELETE entry using ROWID as a unique identifier.  UPDATE  As it does for the actual table, Oracle needs to preserve the pre-DML state of the row.  DELETE  The entire row should be preserved to be restored if needed.
  • 75. 75 of 90 Solution (1) Views based on package variables require:  Object collection  Package to store  Very non-trivial triggers  CREATE TYPE dept_gtt_ot IS OBJECT (deptno NUMBER, dname VARCHAR2(14), loc VARCHAR2(13)) / CREATE TYPE dept_gtt_nt IS TABLE OF dept_gtt_ot /
  • 76. 76 of 90 CREATE OR REPLACE PACKAGE dept_gtt_pkg IS TYPE pk_tt IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; v_pk_tt pk_tt; v_dept_tt dept_gtt_nt:=dept_gtt_nt(); FUNCTION f_getDept_tt RETURN dept_gtt_nt; END; / CREATE OR REPLACE PACKAGE BODY dept_gtt_pkg IS FUNCTION f_getDept_tt RETURN dept_gtt_nt IS BEGIN RETURN v_dept_tt; END; END; / CREATE OR REPLACE VIEW v_dept_gtt AS SELECT * FROM TABLE(dept_gtt_pkg.f_getDept_tt) / Solution (2)
  • 77. 77 of 90 CREATE OR REPLACE TRIGGER V_DEPT_GTT_IIUD INSTEAD OF INSERT OR DELETE OR UPDATE ON V_DEPT_GTT BEGIN IF INSERTING THEN IF :new.deptno IS NULL THEN raise_application_error(-20001,'Deptno is mandatory'); END IF; IF dept_gtt_pkg.v_pk_tt.exists(:new.deptno) THEN raise_application_error(-20001,'Dept already exists'); END IF; dept_gtt_pkg.v_dept_tt.extend; dept_gtt_pkg.v_pk_tt(:new.deptno) :=dept_gtt_pkg.v_dept_tt.last; dept_gtt_pkg.v_dept_tt(dept_gtt_pkg.v_dept_tt.last):= dept_gtt_ot(:new.deptno,:new.dname,:new.loc); ELSIF DELETING THEN IF :old.deptno IS NOT NULL AND dept_gtt_pkg.v_pk_tt.exists(:old.deptno) THEN dept_gtt_pkg.v_dept_tt.delete (dept_gtt_pkg.v_pk_tt(:old.deptno)); dept_gtt_pkg.v_pk_tt.delete(:old.deptno); END IF; ... Solution (3)
  • 78. 78 of 90 ELSIF UPDATING THEN IF :new.deptno IS NOT NULL AND :old.deptno!=:new.deptno THEN IF dept_gtt_pkg.v_pk_tt.exists(:new.deptno) THEN raise_application_error (-20001,'Cannot have duplicate departments'); ELSE dept_gtt_pkg.v_pk_tt(:new.deptno):= dept_gtt_pkg.v_pk_tt(:old.deptno); dept_gtt_pkg.v_pk_tt.delete(:old.deptno); END IF; END IF; dept_gtt_pkg.v_dept_tt(dept_gtt_pkg.v_pk_tt(:new.deptno)):= dept_gtt_ot(:new.deptno,:new.dname,:new.loc); END IF; END; / Solution (4)
  • 79. 79 of 90 SQL> INSERT INTO v_dept_gtt SELECT * FROM dept WHERE deptno in (10,20); 2 rows created. SQL> select * from v_dept_gtt; DEPTNO DNAME LOC ---------- -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS SQL> INSERT INTO v_dept_gtt(deptno,loc) VALUES (50,'NEW JERSEY'); 1 row created. SQL> UPDATE v_dept_gtt SET dname='DEV' WHERE deptno=50; 1 row updated. SQL> DELETE FROM v_dept_gtt WHERE deptno=20; 1 row deleted. SQL> SELECT * FROM v_dept_gtt; DEPTNO DNAME LOC ---------- -------------- ------------- 10 ACCOUNTING NEW YORK 50 DEV NEW JERSEY Proof of Functionality
  • 80. 80 of 90 Solution Impact System impact:  Significantly less log file switches needed  No sudden slow-downs and hiccups.  Higher memory utilization and CPU overhead  Average response time increased from 0.25 seconds to 0.3 seconds. User impact:  Much more predictable performance = happy users
  • 81. 81 of 90 Story #3: When to stop?
  • 82. 82 of 90 Dangers of Views Views are definitions, not data  Calling view multiple times = doing the same job multiple times.  There may be a moment when persisting query results may be more efficient.  Implementation of persistency depends upon your requirements  Materialized views (lots of options)  Tables + manual refresh scripts
  • 83. 83 of 90 Real World Example Existing solution:  Reporting module is based on very complex views  After corporate merge, data volume quadrupled  Reports started to slow down. Revised Solution:  Core views became materialized with nightly full refresh.  Users gladly accepted daily data lag. Advantage of using views from the beginning:  Simple server-side change did the job!
  • 84. 84 of 90 Story #4: Views as Architectural Tools
  • 85. 85 of 90 Data Modeling Problem ERD data model  Can be perfectly implemented as tables+constraints  Very limited Class model  Much better tool to describe the world  Cannot be directly mapped to table structure
  • 86. 86 of 90 Solution Class model:  Table - perfectly relational  Package - implements UML-related functionality  View – presents class exactly as specified in class model
  • 87. 87 of 90 Illustration (1)  Abstract class:
  • 88. 88 of 90 Illustration (2)  Generated view: CREATE OR REPLACE VIEW person AS select EMPLOYEE_OID PERSON_OID ,'Employee' PERSON_CD ,to_char(NameLast_TX||' '||NameFirst_TX) PERSON_DSP ,NAMEFIRST_TX NAMEFIRST_TX ,NAMELAST_TX NAMELAST_TX from EMPLOYEE union all select CONTACT_OID PERSON_OID ,'Contact' PERSON_CD ,to_char(NameLast_TX||' '||NameFirst_TX) PERSON_DSP ,NAMEFIRST_TX NAMEFIRST_TX ,NAMELAST_TX NAMELAST_TX from CONTACT
  • 89. 89 of 90 Summary Views are significantly more than just stored queries  ... because they are interfaces to the outside world (and even Oracle agrees  ). Effective utilization of the database is impossible without deep knowledge of PL/SQL  … since it is closer to your data than any other language environment. It is important to check for new (or forgotten) features  … because there are LOTS of them!
  • 90. 90 of 90 Contact Information  Michael Rosenblum – mrosenblum@dulcian.com  Dulcian, Inc. website - www.dulcian.com  Blog: wonderingmisha.blogspot.com Available NOW: Oracle PL/SQL Performance Tuning Tips & Techniques