Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this...

18
BASEL | BERN | BRUGG | BUCHAREST | DÜSSELDORF | FRANKFURT A.M. | FREIBURG I. BR. | GENEVA HAMBURG | COPENHAGEN | LAUSANNE | MANNHEIM | MUNICH | STUTTGART | VIENNA | ZURICH BASEL | BERN | BRUGG | BUCHAREST | DÜSSELDORF | FRANKFURT A.M. | FREIBURG I. BR. | GENEVA HAMBURG | COPENHAGEN | LAUSANNE | MANNHEIM | MUNICH | STUTTGART | VIENNA | ZURICH danischnider.wordpress.com @dani_schnider Avoid „Horror Queries“ Keep Your SQL Simple and Fast Dani Schnider

Transcript of Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this...

Page 1: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

BASEL | BERN | BRUGG | BUCHAREST | DÜSSELDORF | FRANKFURT A.M. | FREIBURG I. BR. | GENEVA HAMBURG | COPENHAGEN | LAUSANNE | MANNHEIM | MUNICH | STUTTGART | VIENNA | ZURICHBASEL | BERN | BRUGG | BUCHAREST | DÜSSELDORF | FRANKFURT A.M. | FREIBURG I. BR. | GENEVA HAMBURG | COPENHAGEN | LAUSANNE | MANNHEIM | MUNICH | STUTTGART | VIENNA | ZURICH

danischnider.wordpress.com@dani_schnider

Avoid „Horror Queries“Keep Your SQL Simple and FastDani Schnider

Page 2: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

BASEL | BERN | BRUGG | BUCHAREST | COPENHAGEN | DÜSSELDORF | FRANKFURT A.M. | FREIBURG I.BR. GENEVA | HAMBURG | LAUSANNE | MANNHEIM | MUNICH | STUTTGART | VIENNA | ZURICH

Dani Schnider• Senior Principal Consultant at Trivadis AG in

Glattbrugg/Zurich

• Trainer of several Trivadis courses

• Co-Author of Books “Data Warehousing mitOracle” and “Data Warehouse Blueprints”

• Oracle ACE

@dani_schnider danischnider.wordpress.com

Page 3: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Note on this presentation

• The session presents five examples of complex SQL statements that are simplified

step-by-step to improve performance. The slides consist of numerous individual steps

that are difficult to understand without a "soundtrack".

• For this reason, many slides have been omitted from this download version. Instead, a

brief explanation is given for each example of the actions used to improve query

performance.

Page 4: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Reduction of Complexity

Page 5: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Reduction of ComplexitySELECT CAST( 'GELDMARKT Anzahl Records pro AKTLZSSATZ' AS CHAR (50)) AS KZAHLID,

CASEWHEN CONVERT( table1.zinssatz, 'WE8EBCDIC500', 'UTF8') < CONVERT( CAST( '00000001.0000000' AS CHAR (17)), 'WE8EBCDIC500', 'UTF8')THEN odst1.LEGACY.concatNullable( '0', CAST( TO_CHAR( ltrim( table1.zinssatz, '0')) AS CHAR (50)))ELSE CAST( TO_CHAR( ltrim( table1.zinssatz, '0')) AS CHAR (50))

END AS KEYFIELD ,CAST( TO_CHAR( CAST( COUNT( *) AS NUMBER (15, 0)), '000000000000000.') AS CHAR (17)) AS WERT ,table1.mandcd AS MANDCD

FROM(

SELECT DISTINCT gesprd.par_id AS parnr ,CAST( gesprdb.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprdb.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprdb.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprdb.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( bfcall.abw_stnrd_zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz ,'' AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtgesprd gesprdbON gesprdb.inh_par_tech_id = gesprd.inh_par_tech_id

AND gesprdb.proktgrp_art_cd IN ('000')AND gesprdb.proktgrp_typ_cd = '033'

JOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprdb.gesch_tech_id

AND ggvprd.gg_verb_typ_cd = 'UEVV'AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tbfcall bfcallON bfcall.kto_gesch_tech_id = gesprdb.gesch_tech_idJOIN odst1.tbfkkto bfkktoON bfkkto.kto_gesch_tech_id = bfcall.kto_gesch_tech_idJOIN odst1.tgesggv gesggvbON gesggvb.gesch_tech_id = gesprdb.gesch_tech_id

AND gesggvb.gg_verb_typ_cd IN ('CBX4', 'CBX2')WHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd IN ('030', '059')UNIONSELECT DISTINCT gesprd.par_id AS parnr ,

CAST( gesprdb.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprdb.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprdb.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprdb.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( bffest.vereinb_zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz,'' AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtgesprd gesprdbON gesprdb.inh_par_tech_id = gesprd.inh_par_tech_id

AND gesprdb.proktgrp_art_cd IN ('000')AND gesprdb.proktgrp_typ_cd = '033'

JOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprdb.gesch_tech_id

AND ggvprd.gg_verb_typ_cd = 'UEVV'AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tbffest bffestON bffest.kto_gesch_tech_id = gesprdb.gesch_tech_id

AND bffest.lfzt_bis_dt >= to_date('2018-03-28','yyyy-mm-dd')JOIN odst1.tbfkkto bfkktoON bfkkto.kto_gesch_tech_id = bffest.kto_gesch_tech_idJOIN odst1.tgesggv gesggvbON gesggvb.gesch_tech_id = gesprdb.gesch_tech_id

AND gesggvb.gg_verb_typ_cd IN ('CBX4', 'CBX2')WHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd IN ('030', '059')UNIONSELECT DISTINCT gesprd.par_id AS parnr ,

CAST( gesprd.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprd.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprd.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprd.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( gdepos.zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz,CAST( gdepos.ntv_inst_id AS CHAR (100)) AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprd.gesch_tech_id

AND ggvprd.gg_verb_typ_cd IN ('UEVV', 'UEVD')AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tgdepos gdeposON gdepos.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdepos.inst_typ_cd IN ('MMKTCALL', 'MMKTTIME', 'FIDT', 'FIDC', 'FIDD_TIME', 'FIDD_CALL')LEFT JOIN odst1.tgdepob gdepobON gdepob.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdepob.pos_tech_id = gdepos.pos_tech_idLEFT JOIN

(SELECT gde_gesch_tech_id,

pos_tech_id ,buch_stat_cd

FROM odsh1.TGDEGMA gdegmaWHERE gdegma.tr_dt =

(SELECT MAX( gdegma1.tr_dt)FROM odsh1.TGDEGMA gdegma1WHERE gdegma1.pos_tech_id = CAST( gdegma.pos_tech_id AS CHAR (255))

AND gdegma.abstbisdat = to_date( '31.12.2999', 'DD.MM.YYYY'))

)gdegma

ON gdegma.gde_gesch_tech_id = gdepos.gde_gesch_tech_idAND gdegma.pos_tech_id = gdepos.pos_tech_idAND gdegma.buch_stat_cd = 'G'

LEFT JOIN(

SELECT gde_gesch_tech_id,pos_tech_id ,buch_stat_cd

FROM odsh1.TGDETHA gdethaWHERE gdetha.tr_dt =

(SELECT MAX( gdetha1.tr_dt)FROM odsh1.TGDETHA gdetha1WHERE gdetha1.pos_tech_id = CAST( gdetha.pos_tech_id AS CHAR (255))

AND gdetha.abstbisdat = to_date( '31.12.2999', 'DD.MM.YYYY'))

)gdetha

ON gdetha.gde_gesch_tech_id = gdepos.gde_gesch_tech_idAND gdetha.pos_tech_id = gdepos.pos_tech_idAND gdetha.buch_stat_cd = 'G'

LEFT JOIN odst1.tgdektv gdektvON gdektv.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdektv.iso_ausw_whg_cd = gdepos.iso_pos_whg_cdWHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd = '077')table1

GROUP BY table1.zinssatz,table1.mandcd

SELECT CAST( 'GELDMARKT Anzahl Records pro AKTLZSSATZ' AS CHAR (50)) AS KZAHLID,CASE

WHEN CONVERT( table1.zinssatz, 'WE8EBCDIC500', 'UTF8') < CONVERT( CAST( '00000001.0000000' AS CHAR (17)), 'WE8EBCDIC500', 'UTF8')THEN odst1.LEGACY.concatNullable( '0', CAST( TO_CHAR( ltrim( table1.zinssatz, '0')) AS CHAR (50)))ELSE CAST( TO_CHAR( ltrim( table1.zinssatz, '0')) AS CHAR (50))

END AS KEYFIELD ,CAST( TO_CHAR( CAST( COUNT( *) AS NUMBER (15, 0)), '000000000000000.') AS CHAR (17)) AS WERT ,table1.mandcd AS MANDCD

FROM(

SELECT gesprd.par_id AS parnr ,CAST( gesprdb.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprdb.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprdb.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprdb.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( bfcall.abw_stnrd_zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz ,'' AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtgesprd gesprdbON gesprdb.inh_par_tech_id = gesprd.inh_par_tech_id

AND gesprdb.proktgrp_art_cd IN ('000')AND gesprdb.proktgrp_typ_cd = '033'

JOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprdb.gesch_tech_id

AND ggvprd.gg_verb_typ_cd = 'UEVV'AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tbfcall bfcallON bfcall.kto_gesch_tech_id = gesprdb.gesch_tech_idJOIN odst1.tbfkkto bfkktoON bfkkto.kto_gesch_tech_id = bfcall.kto_gesch_tech_idJOIN odst1.tgesggv gesggvbON gesggvb.gesch_tech_id = gesprdb.gesch_tech_id

AND gesggvb.gg_verb_typ_cd IN ('CBX4', 'CBX2')WHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd IN ('030', '059')UNIONSELECT gesprd.par_id AS parnr ,

CAST( gesprdb.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprdb.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprdb.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprdb.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( bffest.vereinb_zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz,'' AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtgesprd gesprdbON gesprdb.inh_par_tech_id = gesprd.inh_par_tech_id

AND gesprdb.proktgrp_art_cd IN ('000')AND gesprdb.proktgrp_typ_cd = '033'

JOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprdb.gesch_tech_id

AND ggvprd.gg_verb_typ_cd = 'UEVV'AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tbffest bffestON bffest.kto_gesch_tech_id = gesprdb.gesch_tech_id

AND bffest.lfzt_bis_dt >= to_date('2018-03-28','yyyy-mm-dd')JOIN odst1.tbfkkto bfkktoON bfkkto.kto_gesch_tech_id = bffest.kto_gesch_tech_idJOIN odst1.tgesggv gesggvbON gesggvb.gesch_tech_id = gesprdb.gesch_tech_id

AND gesggvb.gg_verb_typ_cd IN ('CBX4', 'CBX2')WHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd IN ('030', '059')UNIONSELECT gesprd.par_id AS parnr ,

CAST( gesprd.gesch_id AS CHAR (1)) AS applnr ,CAST( SUBSTR( gesprd.gesch_id, 2, 2) AS CHAR (2)) AS hbnr ,CAST( SUBSTR( gesprd.gesch_id, 4, 3) AS CHAR (3)) AS zwnr ,CAST( SUBSTR( gesprd.gesch_id, 7, 8) AS CHAR (8)) AS geschnr ,CAST( ltrim( TO_CHAR( CAST( gdepos.zss_pt AS NUMBER (15, 7)), '00000000.0000000')) AS CHAR (17)) AS zinssatz,CAST( gdepos.ntv_inst_id AS CHAR (100)) AS inst_id ,gesprd.mandcd AS mandcd

FROM odst1.mqtgesprd gesprdJOIN odst1.mqtggvprd ggvprdON ggvprd.gesch_tech_id = gesprd.gesch_tech_id

AND ggvprd.gg_verb_typ_cd IN ('UEVV', 'UEVD')AND ggvprd.zgd_proktgrp_art_cd = '009'AND ggvprd.zgd_proktgrp_typ_cd = '077'

JOIN odst1.tgdepos gdeposON gdepos.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdepos.inst_typ_cd IN ('MMKTCALL', 'MMKTTIME', 'FIDT', 'FIDC', 'FIDD_TIME', 'FIDD_CALL')LEFT JOIN odst1.tgdepob gdepobON gdepob.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdepob.pos_tech_id = gdepos.pos_tech_idLEFT JOIN odst1.tgdektv gdektvON gdektv.gde_gesch_tech_id = gesprd.gesch_tech_id

AND gdektv.iso_ausw_whg_cd = gdepos.iso_pos_whg_cdWHERE gesprd.proktgrp_art_cd = '001'

AND gesprd.proktgrp_typ_cd = '077')table1

GROUP BY table1.zinssatz,table1.mandcd

2 seconds> 1 hour

In the first example, two unneeded left outer joins were identified, which can be omitted without affecting the result set. With this small change, the response time could be reduced from more than one hour to two seconds.

Page 6: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Performance Tuning without

Database Access

Page 7: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

SELECT S1.DEPTNO,S1.JOB,MIN (S1.EMPNO) AS EMPNO,LTRIM (MAX (SYS_CONNECT_BY_PATH (S1.EMPNO, ';'))

KEEP (DENSE_RANK LAST ORDER BY S1.curr), ';') AS EMPFAENGERLISTEFROM (SELECT DEPTNO,

JOB,EMPNO,ROW_NUMBER () OVER (PARTITION BY DEPTNO, JOB

ORDER BY EMPNO) AS curr,ROW_NUMBER () OVER (PARTITION BY DEPTNO, JOB

ORDER BY EMPNO) – 1 AS prevFROM EMPWHERE DEPTNO > 0) S1

GROUP BY S1.DEPTNO, S1.JOBCONNECT BY S1.prev = PRIOR S1.curr

AND S1.DEPTNO = PRIOR S1.DEPTNOSTART WITH curr = 1) VERSANDINSTRORDER BY ASSET_WID, VERSANDKLASSESELECT DEPTNO,

JOB,MIN (EMPNO) AS EMPNO,LISTAGG(EMPNO, ';')

WITHIN GROUP (ORDER BY EMPNO)AS EMPFAENGERLISTE

FROM EMPWHERE DEPTNO > 0GROUP BY DEPTNO, JOB

In the second example, a complex query was replaced by a simpler statement using LISTAGG, which runs much faster and is easier to understand. This example is described in detail here:https://danischnider.wordpress.com/2018/04/03/keep-your-sql-simple-and-fast/

Page 8: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

An Expensive Attribute

Page 9: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

SELECT state_filing_number,legal_entity_name,toi_desc,sub_toi_desc,state_full_desc,project_lead,state_lead,pr_state_status,response_date,form_type_desc,state_tracking_num,serff_track_nbr,circular_number_txt,request_effective_date,effective_date,status_date,state_req_uid

FROM rah.vw_state_tab_dataWHERE legal_entity_id IN (6)ORDER BY state_desc;

Simple Query on a View

The calculation of an attribute STATUS_DATE in a view became very inefficient due to several nested subselects. Using a subquery factoring clause (WITH statement) and a CASE statement, the response time has been reduced from several minutes to a few seconds.

Page 10: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Make it FasterStep by Step

Page 11: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Query on daily accounting data too slow

SELECT SECURITY_CODE, RATING_AGENCY, RATING, RATING_DATEFROM V_IF_SRAM_INSTR_RATINGSWHERE ACCOUNTING_DATE = TO_DATE('20180513','yyyymmdd');

12 seconds1 minute29 minutes> 2 hours

By using several performance features in two nested views, it was possible to speed up the frequent query for a single date step by step.

Page 12: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

A PL/SQL Journey

Page 13: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

It is a very bad idea to call PL/SQL functions containing SQL statements in the SELECT or WHERE part of a SQL statement because the locally called SQL statement is executed for every row of the query. If this local SQL statement calls other PL/SQL functions, the performance of the main query is getting worse and worse.

Page 14: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

O or 1?

Page 15: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

SELECT COUNT(*) FROM dual WHERE '1' IN(SELECT DISTINCT DECODE(b.nr_anzdreh, 1, '1', NVL(c.nr_in_bulk, '0'))FROM(SELECT DISTINCT h.nr_in_bulk,h.n_beh,h.n_area

FROM c_lt_beh h,c_logskd i

WHERE h.c_status = 'O'AND h.kz_behtyp = 'T'AND h.nr_in_bulk = DECODE(i.nr_anzdreh,1,h.nr_in_bulk,'1')AND i.n_track ='ABR_'||h.n_area) c,

(SELECT DISTINCT nr_anzdreh, n_track FROM c_logskdwhere n_track LIKE 'ABR_M%') d,(SELECT DISTINCT e.nr_in_bulk,e.n_area,e.n_beh

FROM c_lt_beh eWHERE e.c_status = 'O'AND to_number(e.nr_in_bulk) =(SELECT MAX(to_number(g.nr_in_bulk))FROM c_lt_beh gWHERE g.c_status = 'O'AND g.n_area = e.n_areaAND g.n_beh = e.n_beh)

) f,c_lt_beh a,c_logskd b

WHERE b.n_track = 'ABR_'||a.n_areaAND d.n_track = 'ABR_'||a.n_areaAND a.n_area = c.n_areaAND a.n_area = f.n_areaAND d.nr_anzdreh = DECODE(d.nr_anzdreh,1,1,to_number(f.nr_in_bulk))AND c.n_beh = f.n_beh)

FROM (SELECT n_area,n_beh,MAX(TO_NUMBER(nr_in_bulk)) AS nr_in_bulk

FROM c_lt_behWHERE c_status = 'O'GROUP BY n_area, n_beh) f

JOIN c_logskd bON (b.n_track = 'ABR_'||f.n_area AND

f.nr_in_bulk = DECODE(b.nr_anzdreh,1,f.nr_in_bulk,'1'))JOIN c_logskdwhere dON (d.n_track = 'ABR_'||f.n_area AND

d.nr_anzdreh = DECODE(d.nr_anzdreh,1,1,f.nr_in_bulk))WHERE f.kz_behtyp = 'T'AND d.n_track LIKE 'ABR_M%'

(SELECT n_area,n_beh,MAX(TO_NUMBER(nr_in_bulk)) AS nr_in_bulk

FROM c_lt_behWHERE c_status = 'O'GROUP BY n_area, n_beh) f

A query that has been extended over the years is not only difficult to read, it is also slow. A complete reimplementation made it possible to simplify and accelerate the query that returns a flag of 0 or 1.

Page 16: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Summary

Page 17: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

Summary

SQL Performance Tuning is Hard Work

– … but effective

– Massive performance improvements are possible

Reduce complexitity of SQL statements

– Filtering the data set as soon a possible

– Avoid multiple executions

– The easier, the better – for us and for the optimizer

Keep Your SQL Simple and Fast

Page 18: Avoid 'Horror Queries': Keep Your SQL Simple and Fast · Avoid„Horror Queries“ ... Note on this presentation •The session presents five examples of complex SQL statements that

https://danischnider.wordpress.com/2018/04/03/keep-your-sql-simple-and-fast/https://youtu.be/CrJYqHtulGg