SlideShare a Scribd company logo
1 of 32
Download to read offline
Think simple and spare
yourself a facepalm
Michal Simonik
@michalsimonik
misimonik@gmail.com
http://www.michalsimonik.com
www.anakreongames.com
Independent consultant
+11 years in IT
+10 years with Oracle
Database Architect
Data Modeling and Tuning
SQL Tuning
Database Troubleshooting
Consulting
Michal Simonik
© 2015
About me
Think simple and spare
yourself a facepalm
D
on’t afraid
to
ask
:)
Michal Simonik
© 2015
Few things before we start ...
Think simple and spare
yourself a facepalm
● Know your enemy
○ Format the code fist
○ It might be good to paint a picture
○ What are the table sizes?
○ What are their relations
○ What about selectivity?
○ What indexes do I have at my disposal?
○ Check database statistics!
■ 50% of time you’re done after that
Michal Simonik
© 2015
Few things before we start ...
Think simple and spare
yourself a facepalm
● Golden rules
○ Eliminate as soon as possible as much as possible
○ Most important questions are
■ Where do I start?
■ Which table I take next
○ Be precise
■ You don’t want to read database blocks just to throw them away
● If it’s possible - sometimes brute force is necessary
Michal Simonik
© 2015
Few things before we start ...
Think simple and spare
yourself a facepalm
● What do we tune?
○ Resources
■ CPU
■ I/O
■ Memory (can manifest as I/O)
■ Network
○ Locks
○ Restrictions based on application design
Michal Simonik
© 2015
How to measure
Think simple and spare
yourself a facepalm
● How to measure
○ Compare what is comparable - time is just a good hint!
■ Logical reads
■ Memory
○ Compare under same conditions
■ Data
■ Buffer cache
■ Shared pool
■ Beware of different environments
● Test vs Production
Michal Simonik
© 2015
How to test
Think simple and spare
yourself a facepalm
1. ALTER SYSTEM FLUSH SHARED_POOL;
a. EXEC DBMS_SHARED_POOL.PURGE(‘adress, hash’,'C');
2. ALTER SYSTEM FLUSH BUFFER_CACHE;
a. DBMS_RESULT_CACHE.FLUSH;
3. Run old SQL with GATHER_PLAN_STATISTICS hint - Fetch whole query!
4. ALTER SYSTEM FLUSH BUFFER_CACHE;
a. DBMS_RESULT_CACHE.FLUSH;
5. Run new SQL with GATHER_PLAN_STATISTICS hint - Fetch whole query!
6. Get your SQL IDs
7. SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id, child#,
FORMAT => 'ALLSTATS'));
8. Compare
Michal Simonik
© 2015
SQL Art
Think simple and spare
yourself a facepalm
● What is difficult for you is difficult for
Oracle
○ 6 table join is 720 ways how to join
them (not including indexes)
○ Overcomplicated SQL
○ Views
● You know your data best
○ You should also know what Oracle
can do with them
It’s a ghost!
SELECT *
FROM cards c,
order_items i
WHERE c.id = i.card_id
AND i.ITEM_PRICE > 1.20 *
(SELECT AVG(a.item_price) FROM order_items a WHERE a.card_id = c.id);
Michal Simonik
© 2015
Something to warm you up ...
Think simple and spare
yourself a facepalm
SELECT *
FROM cards c,
order_items i
WHERE c.id = i.card_id
AND i.ITEM_PRICE > 1.20 *
(SELECT AVG(a.item_price) FROM order_items a WHERE a.card_id = c.id);
SELECT *
FROM cards c,
order_items i,
(SELECT card_id,
AVG(item_price) avg_item_price
FROM order_items
GROUP BY card_id
) a
WHERE c.id = i.card_id
AND i.card_id = a.card_id
AND i.ITEM_PRICE > 1.20 * a.avg_item_price;
Michal Simonik
© 2015
Something to warm you up ...
Think simple and spare
yourself a facepalm
MERGE INTO metadata_tab met USING
( SELECT DISTINCT zp,
obd_from_rb,
obd_to_rb,
obd_from_rz,
obd_to_rz
FROM fakta_tab
WHERE module_code = 'P304'
AND period = 201209
) fak ON ( NVL(fak.zp, 0) = NVL(met.zp, 0)
AND NVL(fak.obd_from_rb, 0) = NVL(met.obd_from_rb, 0)
AND NVL(fak.obd_to_rb, 0) = NVL(met.obd_to_rb, 0)
AND NVL(fak.obd_from_rz, 0) = NVL(met.obd_from_rz, 0)
AND NVL(fak.obd_to_rz, 0) = NVL(met.obd_to_rz, 0))
WHEN NOT MATCHED THEN
INSERT
(
id_meta_ident,
zp,
obd_from_rb,
obd_to_rb,
obd_from_rz,
obd_to_rz
)
VALUES
(
metadata_seq.NEXTVAL+100,
fak.zp,
fak.obd_od_rb,
fak.obd_do_rb,
fak.obd_od_rz,
fak.obd_do_rz
);
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | Buffers | Reads |
---------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 1 | | 0 | 252 | 4 |
| 1 | MERGE | METADATA_TAB | 1 | | 0 | 252 | 4 |
| 2 | VIEW | | 1 | | 15 | 252 | 4 |
| 3 | SEQUENCE | METADATA_SEQ | 1 | | 15 | 252 | 4 |
|* 4 | HASH JOIN OUTER BUFFERED | | 4 | 4 | 15 | 0 | 0 |
| 5 | VIEW | | 4 | 4 | 15 | 0 | 0 |
| 6 | HASH UNIQUE | | 4 | 4 | 15 | 0 | 0 |
| 7 | HASH UNIQUE | | 4 | 4 | 59 | 15912 | 10332 |
|* 8 | TABLE ACCESS FULL | FAKTA_TAB | 62 | 2480K| 2544K| 15912 | 10332 |
|* 9 | TABLE ACCESS FULL | METADATA_TAB | 5 | 166 | 180 | 10 | 5 |
---------------------------------------------------------------------------------------------------------
* Optimal memory for HASH - 774k
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
MERGE INTO metadata_tab met USING
( SELECT DISTINCT zp,
obd_from_rb,
obd_to_rb,
obd_from_rz,
obd_to_rz
FROM fakta_tab
WHERE module_code = 'P304'
AND period = 201209
) fak ON ( COALESCE(fak.zp, 0) = COALESCE(met.zp, 0)
AND COALESCE(fak.obd_from_rb, 0) = COALESCE(met.obd_from_rb, 0)
AND COALESCE(fak.obd_to_rb, 0) = COALESCE(met.obd_to_rb, 0)
AND COALESCE(fak.obd_from_rz, 0) = COALESCE(met.obd_from_rz, 0)
AND COALESCE(fak.obd_to_rz, 0) = COALESCE(met.obd_to_rz, 0))
WHEN NOT MATCHED THEN
INSERT
(
id_meta_ident,
zp,
obd_from_rb,
obd_to_rb,
obd_from_rz,
obd_to_rz
)
VALUES
(
metadata_seq.NEXTVAL+100,
fak.zp,
fak.obd_od_rb,
fak.obd_do_rb,
fak.obd_od_rz,
fak.obd_do_rz
);
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
DECLARE
v_null VARCHAR2(32) := NULL;
v_not_null VARCHAR2(32) := 'X';
v_dummy VARCHAR2(32);
BEGIN
FOR l_idx IN 1 .. 1000000
LOOP
v_dummy := NVL(v_null, RAWTOHEX(SYS_GUID()));
END LOOP;
--
FOR l_idx IN 1 .. 1000000
LOOP
v_dummy := NVL(v_not_null, RAWTOHEX(SYS_GUID()));
END LOOP;
END;
/
● NVL
Time NULL: 71.66
Time NOT NULL: 72.39
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
DECLARE
v_null VARCHAR2(32) := NULL;
v_not_null VARCHAR2(32) := 'X';
v_dummy VARCHAR2(32);
BEGIN
FOR l_idx IN 1 .. 1000000
LOOP
v_dummy := NVL(v_null, RAWTOHEX(SYS_GUID()));
END LOOP;
--
FOR l_idx IN 1 .. 1000000
LOOP
v_dummy := NVL(v_not_null, RAWTOHEX(SYS_GUID()));
END LOOP;
END;
/
● NVL
Time NULL: 71.66
Time NOT NULL: 72.39
● COALESCE
Time NULL: 74.54
Time NOT NULL: .08
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
INSERT INTO metadata_tab
SELECT metadata_seq.NEXTVAL,
sel.*
FROM
(SELECT DISTINCT zp_zisku,
obd_od_rb,
obd_do_rb,
obd_od_rz,
obd_do_rz
FROM fakta_tab
WHERE kod_uloha = 'P304'
AND obdobi = 201209
MINUS
SELECT zp_zisku,
obd_od_rb,
obd_do_rb,
obd_od_rz,
obd_do_rz
FROM metadata_tab
) sel;
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | Buffers | Reads |
------------------------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 | | 0 | 186 | 1 |
| 1 | LOAD TABLE CONVENTIONAL | | 1 | | 0 | 186 | 1 |
| 2 | SEQUENCE | METADATA_SEQ | 1 | | 0 | 186 | 1 |
| 3 | VIEW | | 4 | 4 | 0 | 0 | 0 |
| 4 | MINUS | | 4 | | 0 | 0 | 0 |
| 5 | SORT UNIQUE | | 4 | 4 | 15 | 0 | 0 |
|* 6 | TABLE ACCESS FULL | FAKTA_TAB | 62 | 2480K| 2544K| 15912 | 10332 |
| 7 | SORT UNIQUE | | 4 | 166 | 180 | 0 | 0 |
|* 8 | TABLE ACCESS FULL | METADATA_SEQ | 5 | 166 | 180 | 10 | 5 |
------------------------------------------------------------------------------------------------------
* Optimal memory for SORT- 2k
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
● From Oracle 11g Release 2
● Ignores ORA-00001
● Requires unique index
○ ORA-38912 if you pass wrong arguments
● Elegant but slow
INSERT /*+ ignore_row_on_dupkey_index(metadata_tab, metadata_tab_pk) */ INTO metadata_tab
SELECT metadata_seq.NEXTVAL,
sel.*
FROM
(SELECT DISTINCT zp_zisku,
obd_od_rb,
obd_do_rb,
obd_od_rz,
obd_do_rz
FROM fakta_tab
WHERE kod_uloha = 'P304'
AND obdobi = 201209
) sel;
Michal Simonik
© 2015
That’s a good MERGE, right?
Think simple and spare
yourself a facepalm
● Goal is to identify multiplicities
● Present them in form of table
Michal Simonik
© 2015
SELECT from SELECT from
SELECT … and from
SELECT
Think simple and spare
yourself a facepalm
ID Patient ID Data ID of duplicate
1 FWER241 1.1.2015 5
1 FWER241 1.1.2015 11
1 FWER241 1.1.2015 23
2 33GSW52 4.5.2015 632
2 33GSW52 4.5.2015 745
SELECT id_uni, patient_id_uni, procedure_date_uni, id_dpl
FROM
(SELECT uni.procedure_date procedure_date_uni,
uni.patient_id patient_id_uni,
uni.id id_uni,
dpl.procedure_date procedure_date_dpl,
dpl.patient_id patient_id_dpl,
dpl.id id_dpl
FROM
(SELECT master.*
FROM patient_data master
WHERE EXISTS
(SELECT 1
FROM
(SELECT * FROM patient_data) source
WHERE master.procedure_date = source.procedure_date
AND master.patient_id = source.patient_id
AND master.ROWID > source.ROWID
)
) dpl,
(SELECT *
FROM patient_data
WHERE ROWID IN (SELECT ID_ROW
FROM
(SELECT MIN(ROWID) AS ID_ROW, procedure_date,patient_id
FROM patient_data
GROUP BY procedure_date,
patient_id
)
)
) uni
WHERE dpl.procedure_date = uni.procedure_date
AND dpl.patient_id = uni.patient_id
) unirowid,
patient_data master_data
WHERE unirowid.patient_id_uni = master_data.patient_id
AND unirowid.procedure_date_uni = master_data.procedure_date
AND unirowid.id_uni = master_data.id
ORDER BY unirowid.patient_id_uni,
unirowid.procedure_date_uni,
unirowid.id_dpl;
Michal Simonik
© 2015
SELECT from SELECT from
SELECT … and from
SELECT
Think simple and spare
yourself a facepalm
--------------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows | OMem | 1Mem | O/1/M |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | |
| 1 | SORT ORDER BY | | 1 | 2048 | 2048 | 1/0/0|
| 2 | NESTED LOOPS SEMI | | 1 | | | |
|* 3 | HASH JOIN | | 1 | 992K| 992K| 1/0/0|
|* 4 | HASH JOIN | | 1 | 1368K| 1368K| 1/0/0|
| 5 | NESTED LOOPS | | 1 | | | |
| 6 | VIEW | VW_NSO_1 | 10 | | | |
| 7 | HASH GROUP BY | | 10 | 1186K| 1186K| 1/0/0|
| 8 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | |
| 9 | TABLE ACCESS BY USER ROWID| PATIENT_DATA | 1 | | | |
| 10 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | |
| 11 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | |
|* 12 | TABLE ACCESS BY ROWID RANGE | PATIENT_DATA | 1 | | | |
--------------------------------------------------------------------------------------------
Michal Simonik
© 2015
SELECT from SELECT from
SELECT … and from
SELECT
Think simple and spare
yourself a facepalm
WITH tmp AS
(SELECT
/*+ materialize or result_cache */
*
FROM
(SELECT m.patient_id,
m.procedure_date,
m.id,
ROW_NUMBER() OVER (PARTITION BY m.patient_id, m.procedure_date ORDER BY m.patient_id, m.procedure_date) c,
COUNT(*) OVER (PARTITION BY m.patient_id, m.procedure_date) ct
FROM patient_data m
)
WHERE ct > 1
)
SELECT uni.id,
uni.patient_id,
uni.procedure_date,
dpl.id
FROM tmp dpl,
tmp uni
WHERE dpl.patient_id = uni.patient_id
AND dpl.procedure_date = uni.procedure_date
AND uni.c = 1
AND dpl.c > 1;
Michal Simonik
© 2015
SELECT from SELECT from
SELECT … and from
SELECT
Think simple and spare
yourself a facepalm
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows | OMem | 1Mem | O/1/M |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | | | 1024 | 1024 | 1/0/0|
|* 3 | VIEW | | 1 | | | |
| 4 | WINDOW SORT | | 1 | 1024 | 1024 | 1/0/0|
| 5 | TABLE ACCESS FULL | PATIENT_DATA | 1 | | | |
|* 6 | HASH JOIN | | 1 | 814K| 814K| 1/0/0|
|* 7 | VIEW | | 1 | | | |
| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9FC85C_9DE45319 | 1 | | | |
|* 9 | VIEW | | 1 | | | |
| 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9FC85C_9DE45319 | 1 | | | |
------------------------------------------------------------------------------------------------------
Michal Simonik
© 2015
SELECT from SELECT from
SELECT … and from
SELECT
Think simple and spare
yourself a facepalm
PROCEDURE ...
...
seq NUMBER;
BEGIN
...
INSERT INTO dm_owner.ms_cs2vd501011_tmp
(SELECT * FROM csu2011.cs2vd501011@vm15dbv_ora112i WHERE stat_date = p_stat_date_in);
...
FOR sel IN (SELECT * FROM dm_owner.cs2vd501011_tmp)
LOOP
SELECT dmv_s_statobj.NEXTVAL INTO seq FROM dual;
INSERT INTO dmv_t_statobj (id_statobj, … , module)
VALUES (seq, … , p_module_in);
INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('ISEKTOR', … ,seq , 1);
INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('FORMA', … ,seq , 1);
INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('KATP', … ,seq , 1);
INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('MNACE', … ,seq , 1);
INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('POCP', … ,seq , 1);
END LOOP;
...
END;
Michal Simonik
© 2015
Copy and paste INSERT
Think simple and spare
yourself a facepalm
PROCEDURE ...
...
seq NUMBER;
BEGIN
...
INSERT INTO dm_owner.ms_cs2vd501011_tmp
(SELECT z, statjed, isektor, forma, katp, mnace, pocp,NULL seq FROM csu2011.
cs2vd501011@vm15dbv_ora112i WHERE stat_date = p_stat_date_in);
...
INSERT ALL
INTO dmv_t_statobj (id_statobj, … , module)
VALUES (seq, … , p_module_in);
INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('ISEKTOR', … ,seq , 1);
INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('FORMA', … ,seq , 1);
INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('KATP', … ,seq , 1);
INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('MNACE', … ,seq , 1);
INTO dmv_t_msr (kode_p, … , id_fak_meta_neident)
VALUES ('POCP', … ,seq , 1)
SELECT * FROM dm_owner.cs2vd501011_tmp;
...
END;
Michal Simonik
© 2015
Copy and paste INSERT
Think simple and spare
yourself a facepalm
DML trigger for sequence
generation
PROCEDURE delete_order (p_id orders.id%TYPE) IS
BEGIN
dbms_output.put_line('Deleting Order ID: '||p_id);
FOR l_idx IN (SELECT * FROM mtg.order_items WHERE order_id = p_id)
LOOP
dbms_output.put_line('Deleting Item ID: '||l_idx.id);
END LOOP;
DELETE mtg.order_items WHERE order_id = p_id;
END;
Michal Simonik
© 2015
I have to SELECT to see!
Think simple and spare
yourself a facepalm
PROCEDURE delete_order (p_id orders.id%TYPE) IS
TYPE t_id IS TABLE OF mtg.order_items.id%TYPE INDEX BY PLS_INTEGER;
l_id t_id;
BEGIN
dbms_output.put_line('Deleting Order ID: '||p_id);
DELETE mtg.order_items WHERE order_id = p_idRETURNING id BULK COLLECT INTO l_id;
FOR l_idx IN l_id.FIRST .. l_id.LAST
LOOP
dbms_output.put_line('Deleting Item ID: '||l_id(l_idx));
END LOOP;
END;
Michal Simonik
© 2015
I have to SELECT to see!
Think simple and spare
yourself a facepalm
SELECT company,
COUNT(*)
FROM invoices
WHERE can_access( company ) = 1
GROUP BY company;
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 2587 | 2402 | | |
| 1 | VIEW | | 2 | 2587 | 2402 | | |
| 2 | HASH GROUP BY | | 2 | 2587 | 2402 | 17M| 3187K|
| 3 | PARTITION RANGE ALL | | 2 | 586K| 2402 | | |
|* 4 | INDEX FAST FULL SCAN| INVOICES | 82 | 586K| 2402 | | |
-------------------------------------------------------------------------------------------------
Michal Simonik
© 2015
Ultimate facepalm
Think simple and spare
yourself a facepalm
SELECT * FROM
(SELECT /*+ no_merge */
company,
COUNT(*)
FROM invoices
GROUP BY company)
WHERE (SELECT can_access( company ) FROM DUAL) = 1;
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2537 | 1201 | | |
|* 1 | FILTER | | 1 | 2537 | 1201 | | |
| 2 | VIEW | | 1 | 2537 | 1201 | | |
| 3 | HASH GROUP BY | | 1 | 2537 | 1201 | 17M| 3187K|
| 4 | PARTITION RANGE ALL | | 1 | 293K| 1201 | | |
| 5 | INDEX FAST FULL SCAN| INVOICES | 41 | 293K| 1201 | | |
| 6 | FAST DUAL | | 2537 | 2537 | 0 | | |
--------------------------------------------------------------------------------------------------
Michal Simonik
© 2015
Ultimate facepalm
Think simple and spare
yourself a facepalm
SELECT company,
COUNT(*)
FROM invoices
GROUP BY company
HAVING can_access(company) = 1;
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2537 | 1201 | | |
|* 1 | FILTER | | 1 | 2537 | 1201 | | |
| 2 | HASH GROUP BY | | 1 | 2537 | 1201 | 17M| 3187K|
| 3 | PARTITION RANGE ALL | | 1 | 293K| 1201 | | |
| 4 | INDEX FAST FULL SCAN| INVOICES | 41 | 293K| 1201 | | |
-------------------------------------------------------------------------------------------------
Michal Simonik
© 2015
Ultimate facepalm
Think simple and spare
yourself a facepalm
Michal Simonik
© 2015
Thank you for your attention
Think simple and spare
yourself a facepalm
Q&A
@michalsimonik
misimonik@gmail.com
http://www.michalsimonik.com

More Related Content

Viewers also liked

Melbourne zone subs unamed
Melbourne zone subs unamed Melbourne zone subs unamed
Melbourne zone subs unamed Gary Lee
 
PMA_Roxtec_Firebarrier_solution (1) (2)
PMA_Roxtec_Firebarrier_solution (1) (2)PMA_Roxtec_Firebarrier_solution (1) (2)
PMA_Roxtec_Firebarrier_solution (1) (2)Gary Lee
 
7487 DM The Collection Set Menu
7487 DM The Collection Set Menu7487 DM The Collection Set Menu
7487 DM The Collection Set MenuThe Parlour Bar
 
Priča jedne svijeće(1)
Priča jedne svijeće(1)Priča jedne svijeće(1)
Priča jedne svijeće(1)redovnice
 
Priča jedne svijeće(1)
Priča jedne svijeće(1)Priča jedne svijeće(1)
Priča jedne svijeće(1)redovnice
 

Viewers also liked (11)

Melbourne zone subs unamed
Melbourne zone subs unamed Melbourne zone subs unamed
Melbourne zone subs unamed
 
PMA_Roxtec_Firebarrier_solution (1) (2)
PMA_Roxtec_Firebarrier_solution (1) (2)PMA_Roxtec_Firebarrier_solution (1) (2)
PMA_Roxtec_Firebarrier_solution (1) (2)
 
7487 DM The Collection Set Menu
7487 DM The Collection Set Menu7487 DM The Collection Set Menu
7487 DM The Collection Set Menu
 
Presentation2
Presentation2Presentation2
Presentation2
 
RESUME2015
RESUME2015RESUME2015
RESUME2015
 
Resume_Navaneethakrishnan_Exp
Resume_Navaneethakrishnan_ExpResume_Navaneethakrishnan_Exp
Resume_Navaneethakrishnan_Exp
 
Priča jedne svijeće(1)
Priča jedne svijeće(1)Priča jedne svijeće(1)
Priča jedne svijeće(1)
 
West quay road
West quay roadWest quay road
West quay road
 
Demystifying Accessibility Testing
Demystifying Accessibility TestingDemystifying Accessibility Testing
Demystifying Accessibility Testing
 
Priča jedne svijeće(1)
Priča jedne svijeće(1)Priča jedne svijeće(1)
Priča jedne svijeće(1)
 
My Resume-2
My Resume-2My Resume-2
My Resume-2
 

Similar to Think simple with SQL to avoid headaches

PNWPHP -- What are Databases so &#%-ing Difficult
PNWPHP -- What are Databases so &#%-ing DifficultPNWPHP -- What are Databases so &#%-ing Difficult
PNWPHP -- What are Databases so &#%-ing DifficultDave Stokes
 
Joins – which, when and why
Joins – which, when and whyJoins – which, when and why
Joins – which, when and whyMichal Simonik
 
Need for Speed: MySQL Indexing
Need for Speed: MySQL IndexingNeed for Speed: MySQL Indexing
Need for Speed: MySQL IndexingMYXPLAIN
 
With big data comes big responsibility
With big data comes big responsibilityWith big data comes big responsibility
With big data comes big responsibilityERPScan
 
Database and application performance vivek sharma
Database and application performance vivek sharmaDatabase and application performance vivek sharma
Database and application performance vivek sharmaaioughydchapter
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applicationsConnor McDonald
 
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013Sergey Petrunya
 
Oracle SQL tuning with SQL Plan Management
Oracle SQL tuning with SQL Plan ManagementOracle SQL tuning with SQL Plan Management
Oracle SQL tuning with SQL Plan ManagementBjoern Rost
 
Top 10 tips for Oracle performance
Top 10 tips for Oracle performanceTop 10 tips for Oracle performance
Top 10 tips for Oracle performanceGuy Harrison
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql featuresConnor McDonald
 
Query Optimization with MySQL 5.6: Old and New Tricks
Query Optimization with MySQL 5.6: Old and New TricksQuery Optimization with MySQL 5.6: Old and New Tricks
Query Optimization with MySQL 5.6: Old and New TricksMYXPLAIN
 
Automating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAutomating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAPNIC
 
SQL Pass Architecture SQL Tips & Tricks
SQL Pass Architecture SQL Tips & TricksSQL Pass Architecture SQL Tips & Tricks
SQL Pass Architecture SQL Tips & TricksIke Ellis
 
Automating Networks by using API
Automating Networks by using APIAutomating Networks by using API
Automating Networks by using API一清 井上
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesConnor McDonald
 
Embarcadero In Search of Plan Stability Part 1 Webinar Slides
Embarcadero In Search of Plan Stability Part 1 Webinar SlidesEmbarcadero In Search of Plan Stability Part 1 Webinar Slides
Embarcadero In Search of Plan Stability Part 1 Webinar SlidesEmbarcadero Technologies
 
Impala 2.0 Update #impalajp
Impala 2.0 Update #impalajpImpala 2.0 Update #impalajp
Impala 2.0 Update #impalajpCloudera Japan
 

Similar to Think simple with SQL to avoid headaches (20)

PNWPHP -- What are Databases so &#%-ing Difficult
PNWPHP -- What are Databases so &#%-ing DifficultPNWPHP -- What are Databases so &#%-ing Difficult
PNWPHP -- What are Databases so &#%-ing Difficult
 
Joins – which, when and why
Joins – which, when and whyJoins – which, when and why
Joins – which, when and why
 
Need for Speed: MySQL Indexing
Need for Speed: MySQL IndexingNeed for Speed: MySQL Indexing
Need for Speed: MySQL Indexing
 
With big data comes big responsibility
With big data comes big responsibilityWith big data comes big responsibility
With big data comes big responsibility
 
Database and application performance vivek sharma
Database and application performance vivek sharmaDatabase and application performance vivek sharma
Database and application performance vivek sharma
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applications
 
Hello my name is DAX
Hello my name is DAXHello my name is DAX
Hello my name is DAX
 
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
MySQL/MariaDB query optimizer tuning tutorial from Percona Live 2013
 
Oracle SQL tuning with SQL Plan Management
Oracle SQL tuning with SQL Plan ManagementOracle SQL tuning with SQL Plan Management
Oracle SQL tuning with SQL Plan Management
 
Top 10 tips for Oracle performance
Top 10 tips for Oracle performanceTop 10 tips for Oracle performance
Top 10 tips for Oracle performance
 
Partitioning 101
Partitioning 101Partitioning 101
Partitioning 101
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
 
Query Optimization with MySQL 5.6: Old and New Tricks
Query Optimization with MySQL 5.6: Old and New TricksQuery Optimization with MySQL 5.6: Old and New Tricks
Query Optimization with MySQL 5.6: Old and New Tricks
 
Automating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAutomating Networks by Converting into API/Webs
Automating Networks by Converting into API/Webs
 
SQL Pass Architecture SQL Tips & Tricks
SQL Pass Architecture SQL Tips & TricksSQL Pass Architecture SQL Tips & Tricks
SQL Pass Architecture SQL Tips & Tricks
 
SQLd360
SQLd360SQLd360
SQLd360
 
Automating Networks by using API
Automating Networks by using APIAutomating Networks by using API
Automating Networks by using API
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
Embarcadero In Search of Plan Stability Part 1 Webinar Slides
Embarcadero In Search of Plan Stability Part 1 Webinar SlidesEmbarcadero In Search of Plan Stability Part 1 Webinar Slides
Embarcadero In Search of Plan Stability Part 1 Webinar Slides
 
Impala 2.0 Update #impalajp
Impala 2.0 Update #impalajpImpala 2.0 Update #impalajp
Impala 2.0 Update #impalajp
 

Recently uploaded

A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 

Recently uploaded (20)

A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 

Think simple with SQL to avoid headaches

  • 1. Think simple and spare yourself a facepalm Michal Simonik @michalsimonik misimonik@gmail.com http://www.michalsimonik.com
  • 3. Independent consultant +11 years in IT +10 years with Oracle Database Architect Data Modeling and Tuning SQL Tuning Database Troubleshooting Consulting Michal Simonik © 2015 About me Think simple and spare yourself a facepalm D on’t afraid to ask :)
  • 4. Michal Simonik © 2015 Few things before we start ... Think simple and spare yourself a facepalm ● Know your enemy ○ Format the code fist ○ It might be good to paint a picture ○ What are the table sizes? ○ What are their relations ○ What about selectivity? ○ What indexes do I have at my disposal? ○ Check database statistics! ■ 50% of time you’re done after that
  • 5. Michal Simonik © 2015 Few things before we start ... Think simple and spare yourself a facepalm ● Golden rules ○ Eliminate as soon as possible as much as possible ○ Most important questions are ■ Where do I start? ■ Which table I take next ○ Be precise ■ You don’t want to read database blocks just to throw them away ● If it’s possible - sometimes brute force is necessary
  • 6. Michal Simonik © 2015 Few things before we start ... Think simple and spare yourself a facepalm ● What do we tune? ○ Resources ■ CPU ■ I/O ■ Memory (can manifest as I/O) ■ Network ○ Locks ○ Restrictions based on application design
  • 7. Michal Simonik © 2015 How to measure Think simple and spare yourself a facepalm ● How to measure ○ Compare what is comparable - time is just a good hint! ■ Logical reads ■ Memory ○ Compare under same conditions ■ Data ■ Buffer cache ■ Shared pool ■ Beware of different environments ● Test vs Production
  • 8. Michal Simonik © 2015 How to test Think simple and spare yourself a facepalm 1. ALTER SYSTEM FLUSH SHARED_POOL; a. EXEC DBMS_SHARED_POOL.PURGE(‘adress, hash’,'C'); 2. ALTER SYSTEM FLUSH BUFFER_CACHE; a. DBMS_RESULT_CACHE.FLUSH; 3. Run old SQL with GATHER_PLAN_STATISTICS hint - Fetch whole query! 4. ALTER SYSTEM FLUSH BUFFER_CACHE; a. DBMS_RESULT_CACHE.FLUSH; 5. Run new SQL with GATHER_PLAN_STATISTICS hint - Fetch whole query! 6. Get your SQL IDs 7. SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id, child#, FORMAT => 'ALLSTATS')); 8. Compare
  • 9. Michal Simonik © 2015 SQL Art Think simple and spare yourself a facepalm ● What is difficult for you is difficult for Oracle ○ 6 table join is 720 ways how to join them (not including indexes) ○ Overcomplicated SQL ○ Views ● You know your data best ○ You should also know what Oracle can do with them It’s a ghost!
  • 10. SELECT * FROM cards c, order_items i WHERE c.id = i.card_id AND i.ITEM_PRICE > 1.20 * (SELECT AVG(a.item_price) FROM order_items a WHERE a.card_id = c.id); Michal Simonik © 2015 Something to warm you up ... Think simple and spare yourself a facepalm
  • 11. SELECT * FROM cards c, order_items i WHERE c.id = i.card_id AND i.ITEM_PRICE > 1.20 * (SELECT AVG(a.item_price) FROM order_items a WHERE a.card_id = c.id); SELECT * FROM cards c, order_items i, (SELECT card_id, AVG(item_price) avg_item_price FROM order_items GROUP BY card_id ) a WHERE c.id = i.card_id AND i.card_id = a.card_id AND i.ITEM_PRICE > 1.20 * a.avg_item_price; Michal Simonik © 2015 Something to warm you up ... Think simple and spare yourself a facepalm
  • 12. MERGE INTO metadata_tab met USING ( SELECT DISTINCT zp, obd_from_rb, obd_to_rb, obd_from_rz, obd_to_rz FROM fakta_tab WHERE module_code = 'P304' AND period = 201209 ) fak ON ( NVL(fak.zp, 0) = NVL(met.zp, 0) AND NVL(fak.obd_from_rb, 0) = NVL(met.obd_from_rb, 0) AND NVL(fak.obd_to_rb, 0) = NVL(met.obd_to_rb, 0) AND NVL(fak.obd_from_rz, 0) = NVL(met.obd_from_rz, 0) AND NVL(fak.obd_to_rz, 0) = NVL(met.obd_to_rz, 0)) WHEN NOT MATCHED THEN INSERT ( id_meta_ident, zp, obd_from_rb, obd_to_rb, obd_from_rz, obd_to_rz ) VALUES ( metadata_seq.NEXTVAL+100, fak.zp, fak.obd_od_rb, fak.obd_do_rb, fak.obd_od_rz, fak.obd_do_rz ); Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 13. --------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | Buffers | Reads | --------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 1 | | 0 | 252 | 4 | | 1 | MERGE | METADATA_TAB | 1 | | 0 | 252 | 4 | | 2 | VIEW | | 1 | | 15 | 252 | 4 | | 3 | SEQUENCE | METADATA_SEQ | 1 | | 15 | 252 | 4 | |* 4 | HASH JOIN OUTER BUFFERED | | 4 | 4 | 15 | 0 | 0 | | 5 | VIEW | | 4 | 4 | 15 | 0 | 0 | | 6 | HASH UNIQUE | | 4 | 4 | 15 | 0 | 0 | | 7 | HASH UNIQUE | | 4 | 4 | 59 | 15912 | 10332 | |* 8 | TABLE ACCESS FULL | FAKTA_TAB | 62 | 2480K| 2544K| 15912 | 10332 | |* 9 | TABLE ACCESS FULL | METADATA_TAB | 5 | 166 | 180 | 10 | 5 | --------------------------------------------------------------------------------------------------------- * Optimal memory for HASH - 774k Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 14. MERGE INTO metadata_tab met USING ( SELECT DISTINCT zp, obd_from_rb, obd_to_rb, obd_from_rz, obd_to_rz FROM fakta_tab WHERE module_code = 'P304' AND period = 201209 ) fak ON ( COALESCE(fak.zp, 0) = COALESCE(met.zp, 0) AND COALESCE(fak.obd_from_rb, 0) = COALESCE(met.obd_from_rb, 0) AND COALESCE(fak.obd_to_rb, 0) = COALESCE(met.obd_to_rb, 0) AND COALESCE(fak.obd_from_rz, 0) = COALESCE(met.obd_from_rz, 0) AND COALESCE(fak.obd_to_rz, 0) = COALESCE(met.obd_to_rz, 0)) WHEN NOT MATCHED THEN INSERT ( id_meta_ident, zp, obd_from_rb, obd_to_rb, obd_from_rz, obd_to_rz ) VALUES ( metadata_seq.NEXTVAL+100, fak.zp, fak.obd_od_rb, fak.obd_do_rb, fak.obd_od_rz, fak.obd_do_rz ); Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 15. DECLARE v_null VARCHAR2(32) := NULL; v_not_null VARCHAR2(32) := 'X'; v_dummy VARCHAR2(32); BEGIN FOR l_idx IN 1 .. 1000000 LOOP v_dummy := NVL(v_null, RAWTOHEX(SYS_GUID())); END LOOP; -- FOR l_idx IN 1 .. 1000000 LOOP v_dummy := NVL(v_not_null, RAWTOHEX(SYS_GUID())); END LOOP; END; / ● NVL Time NULL: 71.66 Time NOT NULL: 72.39 Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 16. DECLARE v_null VARCHAR2(32) := NULL; v_not_null VARCHAR2(32) := 'X'; v_dummy VARCHAR2(32); BEGIN FOR l_idx IN 1 .. 1000000 LOOP v_dummy := NVL(v_null, RAWTOHEX(SYS_GUID())); END LOOP; -- FOR l_idx IN 1 .. 1000000 LOOP v_dummy := NVL(v_not_null, RAWTOHEX(SYS_GUID())); END LOOP; END; / ● NVL Time NULL: 71.66 Time NOT NULL: 72.39 ● COALESCE Time NULL: 74.54 Time NOT NULL: .08 Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 17. INSERT INTO metadata_tab SELECT metadata_seq.NEXTVAL, sel.* FROM (SELECT DISTINCT zp_zisku, obd_od_rb, obd_do_rb, obd_od_rz, obd_do_rz FROM fakta_tab WHERE kod_uloha = 'P304' AND obdobi = 201209 MINUS SELECT zp_zisku, obd_od_rb, obd_do_rb, obd_od_rz, obd_do_rz FROM metadata_tab ) sel; Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 18. ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | Buffers | Reads | ------------------------------------------------------------------------------------------------------ | 0 | INSERT STATEMENT | | 1 | | 0 | 186 | 1 | | 1 | LOAD TABLE CONVENTIONAL | | 1 | | 0 | 186 | 1 | | 2 | SEQUENCE | METADATA_SEQ | 1 | | 0 | 186 | 1 | | 3 | VIEW | | 4 | 4 | 0 | 0 | 0 | | 4 | MINUS | | 4 | | 0 | 0 | 0 | | 5 | SORT UNIQUE | | 4 | 4 | 15 | 0 | 0 | |* 6 | TABLE ACCESS FULL | FAKTA_TAB | 62 | 2480K| 2544K| 15912 | 10332 | | 7 | SORT UNIQUE | | 4 | 166 | 180 | 0 | 0 | |* 8 | TABLE ACCESS FULL | METADATA_SEQ | 5 | 166 | 180 | 10 | 5 | ------------------------------------------------------------------------------------------------------ * Optimal memory for SORT- 2k Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 19. ● From Oracle 11g Release 2 ● Ignores ORA-00001 ● Requires unique index ○ ORA-38912 if you pass wrong arguments ● Elegant but slow INSERT /*+ ignore_row_on_dupkey_index(metadata_tab, metadata_tab_pk) */ INTO metadata_tab SELECT metadata_seq.NEXTVAL, sel.* FROM (SELECT DISTINCT zp_zisku, obd_od_rb, obd_do_rb, obd_od_rz, obd_do_rz FROM fakta_tab WHERE kod_uloha = 'P304' AND obdobi = 201209 ) sel; Michal Simonik © 2015 That’s a good MERGE, right? Think simple and spare yourself a facepalm
  • 20. ● Goal is to identify multiplicities ● Present them in form of table Michal Simonik © 2015 SELECT from SELECT from SELECT … and from SELECT Think simple and spare yourself a facepalm ID Patient ID Data ID of duplicate 1 FWER241 1.1.2015 5 1 FWER241 1.1.2015 11 1 FWER241 1.1.2015 23 2 33GSW52 4.5.2015 632 2 33GSW52 4.5.2015 745
  • 21. SELECT id_uni, patient_id_uni, procedure_date_uni, id_dpl FROM (SELECT uni.procedure_date procedure_date_uni, uni.patient_id patient_id_uni, uni.id id_uni, dpl.procedure_date procedure_date_dpl, dpl.patient_id patient_id_dpl, dpl.id id_dpl FROM (SELECT master.* FROM patient_data master WHERE EXISTS (SELECT 1 FROM (SELECT * FROM patient_data) source WHERE master.procedure_date = source.procedure_date AND master.patient_id = source.patient_id AND master.ROWID > source.ROWID ) ) dpl, (SELECT * FROM patient_data WHERE ROWID IN (SELECT ID_ROW FROM (SELECT MIN(ROWID) AS ID_ROW, procedure_date,patient_id FROM patient_data GROUP BY procedure_date, patient_id ) ) ) uni WHERE dpl.procedure_date = uni.procedure_date AND dpl.patient_id = uni.patient_id ) unirowid, patient_data master_data WHERE unirowid.patient_id_uni = master_data.patient_id AND unirowid.procedure_date_uni = master_data.procedure_date AND unirowid.id_uni = master_data.id ORDER BY unirowid.patient_id_uni, unirowid.procedure_date_uni, unirowid.id_dpl; Michal Simonik © 2015 SELECT from SELECT from SELECT … and from SELECT Think simple and spare yourself a facepalm
  • 22. -------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows | OMem | 1Mem | O/1/M | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | | | | 1 | SORT ORDER BY | | 1 | 2048 | 2048 | 1/0/0| | 2 | NESTED LOOPS SEMI | | 1 | | | | |* 3 | HASH JOIN | | 1 | 992K| 992K| 1/0/0| |* 4 | HASH JOIN | | 1 | 1368K| 1368K| 1/0/0| | 5 | NESTED LOOPS | | 1 | | | | | 6 | VIEW | VW_NSO_1 | 10 | | | | | 7 | HASH GROUP BY | | 10 | 1186K| 1186K| 1/0/0| | 8 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | | | 9 | TABLE ACCESS BY USER ROWID| PATIENT_DATA | 1 | | | | | 10 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | | | 11 | TABLE ACCESS FULL | PATIENT_DATA | 10 | | | | |* 12 | TABLE ACCESS BY ROWID RANGE | PATIENT_DATA | 1 | | | | -------------------------------------------------------------------------------------------- Michal Simonik © 2015 SELECT from SELECT from SELECT … and from SELECT Think simple and spare yourself a facepalm
  • 23. WITH tmp AS (SELECT /*+ materialize or result_cache */ * FROM (SELECT m.patient_id, m.procedure_date, m.id, ROW_NUMBER() OVER (PARTITION BY m.patient_id, m.procedure_date ORDER BY m.patient_id, m.procedure_date) c, COUNT(*) OVER (PARTITION BY m.patient_id, m.procedure_date) ct FROM patient_data m ) WHERE ct > 1 ) SELECT uni.id, uni.patient_id, uni.procedure_date, dpl.id FROM tmp dpl, tmp uni WHERE dpl.patient_id = uni.patient_id AND dpl.procedure_date = uni.procedure_date AND uni.c = 1 AND dpl.c > 1; Michal Simonik © 2015 SELECT from SELECT from SELECT … and from SELECT Think simple and spare yourself a facepalm
  • 24. ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | E-Rows | OMem | 1Mem | O/1/M | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | | | | | 1 | TEMP TABLE TRANSFORMATION | | | | | | | 2 | LOAD AS SELECT | | | 1024 | 1024 | 1/0/0| |* 3 | VIEW | | 1 | | | | | 4 | WINDOW SORT | | 1 | 1024 | 1024 | 1/0/0| | 5 | TABLE ACCESS FULL | PATIENT_DATA | 1 | | | | |* 6 | HASH JOIN | | 1 | 814K| 814K| 1/0/0| |* 7 | VIEW | | 1 | | | | | 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9FC85C_9DE45319 | 1 | | | | |* 9 | VIEW | | 1 | | | | | 10 | TABLE ACCESS FULL | SYS_TEMP_0FD9FC85C_9DE45319 | 1 | | | | ------------------------------------------------------------------------------------------------------ Michal Simonik © 2015 SELECT from SELECT from SELECT … and from SELECT Think simple and spare yourself a facepalm
  • 25. PROCEDURE ... ... seq NUMBER; BEGIN ... INSERT INTO dm_owner.ms_cs2vd501011_tmp (SELECT * FROM csu2011.cs2vd501011@vm15dbv_ora112i WHERE stat_date = p_stat_date_in); ... FOR sel IN (SELECT * FROM dm_owner.cs2vd501011_tmp) LOOP SELECT dmv_s_statobj.NEXTVAL INTO seq FROM dual; INSERT INTO dmv_t_statobj (id_statobj, … , module) VALUES (seq, … , p_module_in); INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('ISEKTOR', … ,seq , 1); INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('FORMA', … ,seq , 1); INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('KATP', … ,seq , 1); INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('MNACE', … ,seq , 1); INSERT INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('POCP', … ,seq , 1); END LOOP; ... END; Michal Simonik © 2015 Copy and paste INSERT Think simple and spare yourself a facepalm
  • 26. PROCEDURE ... ... seq NUMBER; BEGIN ... INSERT INTO dm_owner.ms_cs2vd501011_tmp (SELECT z, statjed, isektor, forma, katp, mnace, pocp,NULL seq FROM csu2011. cs2vd501011@vm15dbv_ora112i WHERE stat_date = p_stat_date_in); ... INSERT ALL INTO dmv_t_statobj (id_statobj, … , module) VALUES (seq, … , p_module_in); INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('ISEKTOR', … ,seq , 1); INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('FORMA', … ,seq , 1); INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('KATP', … ,seq , 1); INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('MNACE', … ,seq , 1); INTO dmv_t_msr (kode_p, … , id_fak_meta_neident) VALUES ('POCP', … ,seq , 1) SELECT * FROM dm_owner.cs2vd501011_tmp; ... END; Michal Simonik © 2015 Copy and paste INSERT Think simple and spare yourself a facepalm DML trigger for sequence generation
  • 27. PROCEDURE delete_order (p_id orders.id%TYPE) IS BEGIN dbms_output.put_line('Deleting Order ID: '||p_id); FOR l_idx IN (SELECT * FROM mtg.order_items WHERE order_id = p_id) LOOP dbms_output.put_line('Deleting Item ID: '||l_idx.id); END LOOP; DELETE mtg.order_items WHERE order_id = p_id; END; Michal Simonik © 2015 I have to SELECT to see! Think simple and spare yourself a facepalm
  • 28. PROCEDURE delete_order (p_id orders.id%TYPE) IS TYPE t_id IS TABLE OF mtg.order_items.id%TYPE INDEX BY PLS_INTEGER; l_id t_id; BEGIN dbms_output.put_line('Deleting Order ID: '||p_id); DELETE mtg.order_items WHERE order_id = p_idRETURNING id BULK COLLECT INTO l_id; FOR l_idx IN l_id.FIRST .. l_id.LAST LOOP dbms_output.put_line('Deleting Item ID: '||l_id(l_idx)); END LOOP; END; Michal Simonik © 2015 I have to SELECT to see! Think simple and spare yourself a facepalm
  • 29. SELECT company, COUNT(*) FROM invoices WHERE can_access( company ) = 1 GROUP BY company; ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 2587 | 2402 | | | | 1 | VIEW | | 2 | 2587 | 2402 | | | | 2 | HASH GROUP BY | | 2 | 2587 | 2402 | 17M| 3187K| | 3 | PARTITION RANGE ALL | | 2 | 586K| 2402 | | | |* 4 | INDEX FAST FULL SCAN| INVOICES | 82 | 586K| 2402 | | | ------------------------------------------------------------------------------------------------- Michal Simonik © 2015 Ultimate facepalm Think simple and spare yourself a facepalm
  • 30. SELECT * FROM (SELECT /*+ no_merge */ company, COUNT(*) FROM invoices GROUP BY company) WHERE (SELECT can_access( company ) FROM DUAL) = 1; -------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem | -------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2537 | 1201 | | | |* 1 | FILTER | | 1 | 2537 | 1201 | | | | 2 | VIEW | | 1 | 2537 | 1201 | | | | 3 | HASH GROUP BY | | 1 | 2537 | 1201 | 17M| 3187K| | 4 | PARTITION RANGE ALL | | 1 | 293K| 1201 | | | | 5 | INDEX FAST FULL SCAN| INVOICES | 41 | 293K| 1201 | | | | 6 | FAST DUAL | | 2537 | 2537 | 0 | | | -------------------------------------------------------------------------------------------------- Michal Simonik © 2015 Ultimate facepalm Think simple and spare yourself a facepalm
  • 31. SELECT company, COUNT(*) FROM invoices GROUP BY company HAVING can_access(company) = 1; ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | A-Rows | Buffers | OMem | 1Mem | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2537 | 1201 | | | |* 1 | FILTER | | 1 | 2537 | 1201 | | | | 2 | HASH GROUP BY | | 1 | 2537 | 1201 | 17M| 3187K| | 3 | PARTITION RANGE ALL | | 1 | 293K| 1201 | | | | 4 | INDEX FAST FULL SCAN| INVOICES | 41 | 293K| 1201 | | | ------------------------------------------------------------------------------------------------- Michal Simonik © 2015 Ultimate facepalm Think simple and spare yourself a facepalm
  • 32. Michal Simonik © 2015 Thank you for your attention Think simple and spare yourself a facepalm Q&A @michalsimonik misimonik@gmail.com http://www.michalsimonik.com