4/19/2014 Best Practices Hints & Tips e “Novità” SQL A cura di Angelo Sironi A.Sironi 2014 1 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi-row Fetch / multi-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 2 1 4/19/2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 3 Ipotesi ◦ Processore da 1.000 Mips ◦ Ignorato effetto MP ◦ Dati indicativi SQL Statement SET :h = CURRENT DATE SELECT INTO :h FETCH 1 riga Multi-row FETCH 100 righe A.Sironi 2014 Consumo di CPU minimo (microsec (microsec.) microsec.) Istruzioni equivalenti 3 3.000 13 13.000 10 10.000 500 500.000 4 2 4/19/2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 5 Funzione ◦ Fornire informazioni sulla strategia di accesso ai dati scelta dall’ottimizzatore Tipo di accesso (es. guidato da uno o più indici) Sequenza di join Metodo di join Ecc. Invocazione ◦ SQL statico Opzione EXPLAIN ( NO, YES, ONLY) del comando BIND PACKAGE Statement EXPLAIN PACKAGE (nuovo in DB2 10) ◦ SQL statico o dinamico Statement EXPLAIN PrePre-requisiti (minimi) ◦ Esistenza di una copia della tabella user.PLAN_TABLE user A.Sironi 2014 6 3 4/19/2014 EXPLAIN PAKAGE PAKAGE COLLECTION collection -name package-name VERSION version-name COPY copy-id Provoca l’Explain di tutti gli statement del Package ◦ Il DB2 esternalizza in PLAN_TABLE una copia delle informazioni sulle strategia di accesso esistenti in formato interno ◦ Diversamente dal comando BIND EXPLAIN(ONLY), non viene generata una nuova strategia di accesso ◦ Non viene effettuato un BIND ◦ Si applica solo a Package bound con DB2 V9 o successivi A.Sironi 2014 7 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 8 4 4/19/2014 SQL Request SQL Result RELATIONAL DATA SERVICES DATA MANAGER Evaluates STAGE 2 predicates Evaluates STAGE 1 (“sargable”) predicates BUFFER MANAGER A.Sironi 2014 9 Efficienza ◦ Predicati Stage 1 ◦ Indexable ◦ Adeguatamente supportati da indici Stage 1 ◦ Gestiti dal Data Manager nell’accesso al Buffer Pool ◦ Inibitori più comuni: presenza nei predicati di Funzioni scalari (es. T1.C1 = SUBSTR(T2.C1,1,4) ) Espressioni (es. T1.C1 + :h1 = :h2 ) Mismatch di tipo dato (es. T1.C1 = :h1 con C1 SMALLINT e :h1 DECIMAL(7,0)) A.Sironi 2014 10 5 4/19/2014 Tecniche/costrutti da non usare nei predicati ◦ CASE Expression ◦ :hostvar1 = costante OR Colonna = :hostav2 .. ecc. Tecniche tollerate (ottimizzabili esternamente) ◦ WHERE COL1 BETWEEN :hostvar1 AND :hostvar2 AND COL2 BETWEEN : hostvar3 AND :hostvar4 AND ecc. ◦ Uso di “BETWEEN” raccomandato al posto di predicati del tipo WHERE COL1 >= :hostvar1 AND COL1 <= :hostvar2 AND ecc. ◦ Eccezione: :hv BETWEEN COL1 AND COL2 A.Sironi 2014 11 2,3 FETCH per OPEN (di cui una con SQLCODE=100) Ca. 5.000 GETPAGE / OPEN – 3 millisec. millisec. di CPU in media) DECLARE CURS01 CURSOR FOR SELECT ecc. FROM TABLE_1 T1 INNER JOIN TABLE_2 T2 ON … predicati di join … WHERE T1.C1 = :H1 AND T1.C2 = :H2 AND ((CASE :H5 WHEN 0 THEN T1.C3 END = :H3 AND CASE :H5 WHEN 0 THEN T1.C4 END = :H4 ) OR (CASE :H3 WHEN 0 THEN T1.C5 = :H5 ) ) ORDER BY ecc. A.Sironi 2014 12 6 4/19/2014 Caso 1: 1: sono noti i valori di ricerca di C3 e C4 DECLARE CURS01 CURSOR FOR SELECT ecc. FROM TABLE_1 T1 INNER JOIN TABLE_2 T2 ON … predicati di join … WHERE T1.C1 = :H1 AND T1.C2 = :H2 AND T1.C3 = :H3 AND T1.C4 = :H4 ORDER BY ecc. A.Sironi 2014 Caso 2: 2: sono noti i valori di ricerca di C5 DECLARE CURS01 CURSOR FOR SELECT ecc. FROM TABLE_1 T1 INNER JOIN TABLE_2 T2 ON … predicati di join … WHERE T1.C1 = :H1 AND T1.C2 = :H2 AND T1.C5 = :H5 ORDER BY ecc. A.Sironi 2014 7 4/19/2014 Flusso originale (semplificato) OPEN CURS01 FETCH CURS01 Gestisci Riga CLOSE CURS01 ecc. A.Sironi 2014 15 Flusso modificato (semplificato) Caso 1 IF … OPEN CURS01A FETCH CURS01A Caso 2 OPEN CURS01B Gestisci Riga CLOSE CUSR01A FETCH CURS01B CLOSE CURS01B ecc. A.Sironi 2014 16 8 4/19/2014 Cardinalità della Tabella: 3,0 milioni SELECT ecc. INTO :H , … FROM TABLE WHERE C1 = :H1 AND ( '' = :HX OR ID = :HID ) AND ( ( '' = :HY AND 0 = :HZ ) OR ( CX = :HX AND CY = :HY ) ) Valori medi per singola esecuzione ◦ Elapsed Time ◦ Consumo di CPU ◦ Getpage : 10,59 sec. : 2,074 sec. (ca. 2 miliardi di istr.) : 409.406 A.Sironi 2014 17 Cardinalità della Tabella: 7,5 milioni SELECT FROM WHERE AND AND AND AND AND AND AND COUNT ( * ) INTO :H TABLE C1 = :H AND DATA BETWEEN :H AND :H ( C2 IN ( :H , :H ) ) ( :H IN ( C3, C4, ' ' ) ) ( :H IN ( C5 , 0 ) ) ( :H IN ( C6 , ' ' ) ) ( :H IN ( C7 , ' ' ) ) ( :H IN ( C8, C9, ' ( C10 <> 12345 OR ( C10 = 12345 AND C11 <> ‘XXXXXXXXX' )) ' ) ) Valori medi per singola esecuzione ◦ Elapsed Time ◦ Consumo di CPU ◦ Getpage A.Sironi 2014 : 7,097 sec. : 4,432 sec. (ca. 4,5 miliardi di istr.) : 193.443 18 9 4/19/2014 Soluzione raccomandata ◦ Del tutto simile alla precedente ◦ Più semplice, non dovendo gestire OPEN/CLOSE e ciclo di FETCH Si suddivide in due, tre o più casi, a seconda della frequenza d’uso e della capacità di filtro, usando dove possibile predicati di uguaglianza ◦ Caso 1: 1 predicati su C1, C2 (e C5 ?) ◦ Caso 2 2: predicati su C1, C2 e C6 ◦ Caso 3: 3 ecc. Invece dell’operatore CASE, si usino condizioni di BETWEEN, ed eventualmente hint per REOPT Riduzione del consumo di CPU attesa Similmente per il caso 2B ◦ Uno o anche due ordini di grandezza A.Sironi 2014 19 WITH TEMP1 AS (SELECT C1, C2, C3, ecc. FROM TABLE WHERE C1 = :H AND DATA BETWEEN :H AND :H AND ( C2 IN ( :H , :H ) ) AND ( :H IN ( C3, C4, ' ' ) ) AND ( :H IN ( C5 , 0 ) ) AND ( :H IN ( C6 , ' ' ) ) AND ( :H IN ( C7 , ' ' ) ) AND ( :H IN ( C8, C9, ' ' ) ) AND ( C10 <> 12345 OR ( C10 = 12345 AND C11 <> ‘XXXXXXXXX' )) ), TEMP2 AS (SELECT COUNT(*) AS CONTA FROM TEMP1) SELECT T1.*, T2.CONTA FROM TEMP1 T1, TEMP2 T2 A.Sironi 2014 20 10 4/19/2014 SELECT … omissis … FROM TABLE_1 T1 LEFT OUTER JOIN TABLE_2 T2 ON … omissis … WHERE T1.C1 = COALESCE (CAST ( ? AS VARCHAR(8)), T1.C1 ) AND T1.C2 = COALESCE (CAST ( ? AS VARCHAR(5)), T1.C2 ) AND … omissis … AND T1.END_DATE <= CURRENT TIMESTAMP AND COALESCE ( T1.END_DATE , ( CURRENT TIMESTAMP + 1 SECOND ) ) > ( CURRENT TIMESTAMP ) Ambiente DRDA JDBC / ODBC ◦ Il DB2 non riesce ad usare in modo efficiente (Matching Mode) eventuali indici su T1.C1 e/o T1.C2 ◦ Ogni esecuzione della query provoca mediamente la scansione di 17.000 pagine e un consumo di CPU di oltre 170 millisecondi (per Prepare, Open, 2-3 Fetch, Close) A.Sironi 2014 21 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 22 11 4/19/2014 Problemi «logici» in presenza di NULL ◦ ◦ ◦ ◦ Risultati potenzialmente errati Maggiore complessità della codifica SQL Inefficienze Spazio disco e memoria Non abusare nell’uso dei NULL ◦ Evitare di definire colonne come NULL-able, a meno che non se ne possa proprio fare a meno Attenzione: Attenzione: ◦ NULL è il default! A.Sironi 2014 D1: 23 Trovare i Fornitori che è noto che forniscono il Prodotto P1, ma di certo non in una quantità pari a 100 Q1a SELECT FROM WHERE AND R1a DISTINCT FX.COD_F FORNITORI FX FX.PRODOTTO = 'P1' 100 NOT IN ( SELECT FY.QTA FROM FORNITORI FY WHERE FY.COD_F = FX.COD_F AND FY.PRODOTTO = 'P1') ; A.Sironi 2014 12 4/19/2014 D1: Trovare i Fornitori che è noto che forniscono il Prodotto P1, ma di certo non in una quantità pari a 100 Q1b SELECT FROM WHERE AND R1b DISTINCT FX.COD_F FORNITORI FX FX.PRODOTTO = 'P1' NOT EXISTS ( SELECT FY.QTA FROM FORNITORI FY WHERE FY.COD_F = FX.COD_F AND FY.PRODOTTO = 'P1' AND FY.QTA = 100 ) ; A.Sironi 2014 Q2a (tautologia?) SELECT FROM WHERE OR * FORNITORI QTA = 100 QTA <> 100 R2a Q2t (tautologia!) SELECT FROM WHERE OR OR * FORNITORI QTA = 100 QTA <> 100 QTA IS NULL R2t A.Sironi 2014 13 4/19/2014 Q3 SELECT AVG(SALARIO) + AVG(COMM) AS AVG_SAL_1 , AVG(SALARIO+COMM) AS AVG_SAL_2 FROM FORNITORI A.Sironi 2014 Esempio CREATE TABLE TEST ( KEY INTEGER NOT NULL, VALID_FROM TIMESTAMP NOT NULL, VALID_TO TIMESTAMP ) Trovare il record con KEY = :h valido ora SELECT * FROM TEST WHERE VALID_FROM <= CURRENT TIMESTAMP AND (VALID_TO >= CURRENT TIMESTAMP OR VALID_TO IS NULL) Esistono un certo numero di varianti della soluzione precedente ◦ Alcune decisamente inefficienti… A.Sironi 2014 28 14 4/19/2014 SELECT … omissis … FROM TABLE_1 T1 LEFT OUTER JOIN TABLE_2 T2 ON … omissis … WHERE T1.C1 = COALESCE (CAST ( ? AS VARCHAR(8)), T1.C1 ) AND T1.C2 = COALESCE (CAST ( ? AS VARCHAR(5)), T1.C2 ) AND … omissis … AND T1.END_DATE <= CURRENT TIMESTAMP AND COALESCE ( T1.END_DATE , ( CURRENT TIMESTAMP + 1 SECOND ) ) > ( CURRENT TIMESTAMP ) La colonna END_DATE, essendo NULLable, NULLable, non può essere parte della chiave di univocità Il DB2 non riesce ad usare in modo efficiente un eventuale indice sulla colonna END_DATE A.Sironi 2014 29 NULL ◦ Non è un valore della colonna ◦ È un indicatore associato alla colonna ◦ Ogni colonna NULL-able richiede un byte in più Nel tablespace In ogni eventuale indice di cui risulta parte della chiave Su disco e nei buffer pool A.Sironi 2014 30 15 4/19/2014 Colonne Carattere ◦ Usare una stringa di blank SE VARCHAR, impostare LL = 0 Colonne DATE e TIMESTAMP usate per delimitare intervalli di validità ◦ Esempio per datatype DATE LOW-END = valore a scelta / default ‘01.01.0001’ HIGH-END = ‘30.12.9999’ (standard Java e SQL ISO/ANSI Temporal Support) oppure ‘31.12.9999’ ◦ Reperimento del record valido ora SELECT * FROM TEST WHERE VALID_FROM <= CURRENT TIMESTAMP AND VALID_TO > CURRENT TIMESTAMP A.Sironi 2014 Il DB2 10 per z/OS introduce il supporto dello standard ANSI/ISO SQL per le costanti datetime Esempi della sintassi ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ 31 DATE '1977-01-18' -- valid date (ISO format) DATE '18.01.1977' -- valid date (EUR format) DATE '0000-01-18' -- invalid date (bad year) DATE '2010-02-29' -- invalid date (bad day) TIME '24:00:00' -- valid time (JIS, ISO format) TIME '24:00:01' -- invalid time (bad hour) TIME '00.00.00' -- valid time (EUR format) TIME '12:01 AM' -- valid time (USA format) TIMESTAMP '2007-05-14 11:55:00.1234' -- valid (space and colons) Raccomandazione: Raccomandazione: specificare ◦ DATE ‘2010‘2010-0808-06’ invece di ◦ DATE(‘2010 DATE(‘2010(‘2010-0808-06’) per migliorare la portabilità e, forse, anche le prestazioni Evitare codifiche del tipo WHERE CHAR(data, ISO) = :h A.Sironi 2014 32 16 4/19/2014 Prima del DB2 10, il formato del tipo dato TIMESTAMP era fisso e forniva una precisione al microsecondo (10-6 secondi) Con il DB2 10, l’utente può definire la precisione che preferisce ◦ minima = 0 (precisione al secondo) ◦ massima = 12 (precisione al picosecondo = 10-12 secondi) Esempi: Esempi: ◦ ◦ ◦ ◦ TS1 TIMESTAMP(0) TS2 TIMESTAMP(9) TS3 TIMESTAMP(12) CURRENT TIMESTAMP(12) La lunghezza della colonna varia di conseguenza Per i dettagli: dettagli: si veda il Redbook SG24SG24-7892 A.Sironi 2014 33 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 34 17 4/19/2014 Premessa ◦ Batch = elaborazione di massa ◦ Elaborazione di massa richiama in modo connaturale “elaborazione di insiemi / set processing” Set Processing Uno dei cardini del Modello Relazionale Fonte di continui progressi funzionali e prestazionali nell’implementazione dei sistemi e del linguaggio SQL Le varie forme di Prefetch e Block Fetch Query Parallelism Multi-row fetch OLAP Specification Inibitori… ◦ Applicazioni Batch che pretendono di operare come applicazioni OLTP A.Sironi 2014 35 Sintomi ◦ Elaborazione guidata da file sequenziale ◦ Elevato numero di SELECT INTO e/o elevato numero di OPEN CURSOR con pochissime FETCH per OPEN ◦ Spesso associato ad un limitato uso degli operatori relazionali ◦ Non infrequente un elevato numero di accessi a tabelle di pochi record Motivazioni addotte ◦ Riutilizzo del codice A.Sironi 2014 36 18 4/19/2014 Caso tipico di inapplicabilità ◦ Elaborazione guidata da file sequenziale SQL_CALL -------SELECT SELECT SELECT OPEN FETCH CLOSE SELECT OPEN FETCH SELECT CLOSE STMT£ SQL CPUPCT ------- --------- ------0005103 13676256 47.77% 0004771 11320907 40.53% 0003826 1641730 7.82% 0004846 221613 2.51% 0004874 795415 .96% 0005048 221613 .21% 0004548 12495 .11% 0004334 1265 .03% 0004362 16049 .02% 0004035 1871 .00% 0004615 1265 .00% INDB2_TIME -----------01:40:18.094 19:49.657642 06:40.676105 00:22.988164 00:08.288251 00:01.728707 00:11.031098 00:04.849223 00:00.185866 00:01.110174 00:00.009167 INDB2_CPU GETPAGE ------------ -------02:56.577296 8941179 02:29.812458 8348682 00:28.905415 3647381 00:09.285109 638606 00:03.549874 0 00:00.788970 0 00:00.429413 55388 00:00.115000 8823 00:00.087877 0 00:00.028994 878 00:00.004745 0 A.Sironi 2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ ◦ ◦ 37 MultiMulti-row Fetch / multimulti-row Insert Query Parallelism Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ ◦ ◦ ◦ ◦ ◦ Fetch 1 Row Only; Only; Optimize For 1 Row Nuovi costrutti SQL Generazione di Chiavi di Univocità: Oggetto SEQUENCE Temporary Table Stored Procedure Extended Indicator Variable A.Sironi 2014 38 19 4/19/2014 Integrato in alcuni programmi di “utilità “utilità” utilità” ◦ Es. DSNTIAUL ◦ Operano con valore di default = 100 Ogni FETCH legge 100 righe ◦ Punto di massimo vantaggio Vantaggi ◦ Mediamente, 50% ca. di riduzione del consumo di CPU Su letture di milioni di record per OPEN di cursore PrePre-requisiti ◦ Set Processing ◦ Modifiche al codice applicativo A.Sironi 2014 39 Un unico statement di INSERT può inserire una molteplicità di righe (<32,768) da un array Opzioni: Opzioni: ◦ ATOMIC: se va male l’inserimento anche di una sola riga, tutto lo statement fallisce ◦ NOT ATOMIC: ciascuna riga trattata separatamente dale altre Lo statement GET DIAGNOSTICS fornisce informazioni diagnostiche per ciascuna riga per la quale l’inserimento non è andato a buon fine L’SQLCODE indica se ◦ L’inserimento non è andato a buon fine per nessuna riga ◦ L’inserimento è andato a buon fine per tutte le righe ◦ L’inserimento non è andato a buon fine per almeno una riga A.Sironi 2014 40 20 4/19/2014 Ci si può aspettare fino al 40% di riduzione del consumo di CPU ◦ Minore se maggiore è il numero delle colonne e/o il numero degli indici ◦ Maggiore al crescere del numero delle righe inserite per statement di Insert A.Sironi 2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ ◦ ◦ 41 MultiMulti-row Fetch / multimulti-row Insert Query Parallelism Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioneidei consumi di CPU ◦ ◦ ◦ ◦ ◦ ◦ Fetch 1 Row Only; Only; Optimize For 1 Row Nuovi costrutti SQL Generazione di Chiavi di Univocità: Oggetto SEQUENCE Temporary Table Stored Procedure Extended Indicator Variable A.Sironi 2014 42 21 4/19/2014 PrePre-requisiti ◦ Elaborazione per insiemi / query “gravosa” ◦ Tabelle partizionate ◦ Disponibilità di risorse hw (macchina non satura) Attivazione ◦ SQL statico Attivabile al BIND tramite opzione DEGREE (ANY) ◦ SQL dinamico Attivabile tramite comando SQL SET CURRENT DEGREE =‘ANY’ (oppure :hostvar impostata al valore “ANY”) Vantaggi ◦ Parte del consumo (non solo DRDA) scaricato su zIIP ◦ Miglioramento dei tempi di esecuzione ◦ Trasparenza applicativa Cfr. Cfr. Riferimenti [4] A.Sironi 2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ ◦ ◦ 43 MultiMulti-row Fetch / multimulti-row Insert Query Parallelism Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazione dei consumi di CPU ◦ ◦ ◦ ◦ ◦ ◦ Fetch 1 Row Only; Only; Optimize For 1 Row Nuovi costrutti SQL Generazione di Chiavi di Univocità: Oggetto SEQUENCE Temporary Table Stored Procedure Extended Indicator Variable A.Sironi 2014 44 22 4/19/2014 SQL_CALL -------FETCH OPEN SELECT FETCH FETCH OPEN OPEN CLOSE STMT£ ------0006943 0004053 0007088 0007144 0007120 0005797 0006305 0006588 SECT£ ----00002 00002 00011 00004 00003 00003 00004 00002 SQL CPUPCT --------- ------36380455 61.43% 403910 26.34% 403910 3.83% 807836 2.63% 807828 2.55% 403910 .79% 403918 .74% 403910 .57% INDB2_TIME -----------03:14.944890 01:28.554185 00:12.454234 00:08.712145 00:08.419207 00:02.534090 00:02.356381 00:01.847810 INDB2_CPU -----------02:33.245450 01:05.707429 00:09.571059 00:06.562709 00:06.373773 00:01.974218 00:01.845975 00:01.436934 La OPEN 4053 e le FETCH 6943 operano su una tabella di 14.966 righe ◦ Oltre 36,3 milioni di Fetch ◦ Mediamente, Mediamente ogni riga viene letta ca. 2.430 volte! volte Evitabile, Evitabile, senza stravolgere l’architettura dell’applicazione? dell’applicazione? A.Sironi 2014 45 Letture duplicate: evitabili? evitabili? ◦ Sort del file guida sulla base dei criteri di ricerca Se i criteri di ricerca non cambiano, i dati sono già nelle aree di memoria del programma 1234fr345 3245pr543 5639tr321 …… A.Sironi 2014 1847 1847 1849 … bdf5678798 jkefhy7980 kjfh769i89j …. oldkey = 0000 newkey = 1234 IF oldkey <> newkey do EXEC SQL SELECT C1, C2, C4 INTO :c1, :c2, :c3 FROM T1 WHERE K = :newkey ** test SQLCODE MOVE newkey to oldkey enddo 46 23 4/19/2014 E se non è possibile prepre-ordinare il file guida sulla chiave di ricerca? ricerca? Alternative 1. Provare comunque ad utilizzare la tecnica appena indicata anche in assenza di ordinamento ottimale 2. Pre-caricare la tabella in memoria e effettuare ricerche binarie A.Sironi 2014 Disponibile in Cobol da diversi lustri ◦ SEARCH ◦ SEARCH ALL 47 - ricerca seriale (Attenzione ai costi!) – ricerca binaria Consumi ◦ Per tabelle di cardinalità > 1000, fino a due ordini di grandezza di risparmio rispetto ad una SELECT INTO PrePre-requisiti 1. La tabella deve presentare un criterio di univocità 2. Deve essere caricata in memoria ordinata secondo tale criterio 3. La ricerca deve prevedere predicati di uguaglianza in AND logico su tutte le colonne della chiave di univocità 4. La dimensione della tabella deve essere compatibile con al disponibilità di memoria A.Sironi 2014 48 24 4/19/2014 http://shaddy-ethical-hacking.blogspot.it/2013/05/a-c-program-to-binary-search-any-element.html A.Sironi 2014 49 Se la ricerca ◦ Non qualifica tutte le colonne della chiave di univocità ◦ Qualifica una o più colonne con predicato di range ◦ Deve reperire più di una riga Opzioni ◦ Ricerca binaria su valore minimo del predicato di range o della colonna priva di predicato (se se noto …); oppure … ◦ Assegnazione di una chiave di univocità surrogata (v. esempio alla pagina successiva) A.Sironi 2014 50 25 4/19/2014 Caso tipico ◦ Ricerca del valore corrente ad una certa data Tasso di interesse Costo o prezzo di vendita di un articolo Ecc. Struttura dati essenziale ◦ ◦ ◦ ◦ KEY INI_VAL END_VAL Valore – Chiave naturale – Data di inizio validità - Data di fine validità - Dato di interesse Ricerca del VALORE in vigore alla data di interesse SELECT VALORE FROM T1 WHERE KEY = ? AND INI_VAL <= ? AND END_VAL > ? A.Sironi 2014 51 Il programma carica in memoria il risultato della query seguente SELECT KEY , ROW_NUMBER() OVER(PARTITION BY KEY ORDER BY END_VAL ASC ) AS ROWNUM , INI_VAL, END_VAL, VALORE DESC FROM TABLE ORDER BY KEY, 2 A.Sironi 2014 52 26 4/19/2014 Il programma, programma, invece di interrogare il DB2 ◦ esegue una ricerca binaria per uguaglianza sul valore di KEY di interesse e RWNUM =1 ◦ Prosegue con una ricerca sequenziale del dato di interesse (predicati temporali) fino a rottura di KEY Efficienza garantita se il numero medio di righe per chiave naturale (KEY, nell’esempio) nell’esempio) è almeno di un ordine di grandezza inferiore alla cardinalità di KEY ◦ Es. Card di KEY = 1.000; Table Card = 10.000 A.Sironi 2014 53 Esempio ◦ Tabella con chiave di univocità su (C1, C2, C3) ◦ Esigenza: Reperire tutte le righe on valori noti per C1 e C3 ◦ Caricamento in memoria da tabella DB2 tramite SELECT * FROM (SELECT T.* , ROW_NUMBER() OVER(PARTITION BY C1,C3 ORDER BY C2) AS ROW_NUM FROM TABC123 T ) AS X ORDER BY C1, C3, ROW_NUM Note: 1. 2. (C1, C3, ROW_NUM) è chiave di univocità Tecnica applicabile anche se (C1, C2, C3) non è chiave di univocità A.Sironi 2014 54 27 4/19/2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row e linguaggio SQL ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 55 Fetch First n Rows Only ◦ Indica al DB2 che l’applicazione è interessata solo alle prime n righe dell’answer set Originariamente utilizzabile solo nell’outer SELECT Ora (dal DB2 9) utilizzabile anche nelle sub-SELECT Fetch First 1 Row ◦ Utilizzare nelle SELECT INTO che potrebbero restituire più di una riga ◦ Utilizzare nella definizione dei cursori dai quali si leggerà sempre solo la prima riga Trasformare questi cursori in SELECT INTO ◦ Utilizzare quando la SELECT INTO è interessata alla riga più recente o più vecchia, evitando la subSelect A.Sironi 2014 56 28 4/19/2014 SELECT …… FROM MYTABLE A WHERE A.COL1 = :H1 AND … AND A.COLX = ( SELECT MAX ( B.COLX ) FROM MYTABLE B WHERE B.COL_1 = :H1 AND … ) SELECT …… FROM MYTABLE A WHERE A.COL1 = :H1 AND … ORDER BY COLX DESC FETCH FIRST 1 ROWS ONLY A.Sironi 2014 57 Optimize For n Row ◦ Un’indicazione all’Ottimizzatore per privilegiare la strategia di accesso meno costosa per il reperimento delle prime n righe ◦ L’applicazione può comunque recuperare tutte le righe di interesse dell’answer set Optimize For 1 Row (modifiche del DB2 10) ◦ Simile al comportamento pre DB2 10, ma il DB2 evita di prendere in considerazione qualunque strategia di accesso, anche se meno costosa, che comporti una fase di sort ◦ La strategia scelta può risultare più costosa delle attese ◦ L’Apar PM56845 permette di operare come pre DB2 10 ◦ Alternativa suggerita, se non si usa l’opzione dell’apar PM56845 OPTIMIZE FOR 2 ROWS A.Sironi 2014 58 29 4/19/2014 Permette di condizionare l’esecuzione di Insert e Update di una tabella a partire da un elenco di variabili o un array di variabili ◦ Quando le condizioni imposte sono verificate, si esegue l’Update ◦ Quando le condizioni non sono verificate, si esegue l’Insert ◦ Provoca l’esecuzione di eventuali Trigger di Update / Insert ◦ La sequenza di esecuzione di Update / Insert può avere un impatto sulle prestazioni Questa implementazione è meno potente di uella resa disponibile dal DB2 for LUW, che permette ◦ Una subselect come input all’operazione di Merge ◦ L’esecuzione condizionata di Update, Insert e Delete A.Sironi 2014 59 MERGE INTO items AS T USING (VALUES (:item_id, :qty)) AS N(id, qty) ON T.id = N.id WHEN MATCHED THEN UPDATE SET qty_on_hand = T.qty_on_hand + N.qty, T.upsert_ts = current timestamp WHEN NOT MATCHED THEN INSERT (id, qty_on_hand, upsert_ts) VALUES (N.id, N.qty, current timestamp) Si veda un esempio con un array come input in Materiale di Riferimento [3] A.Sironi 2014 60 30 4/19/2014 Il DB2 V8 ha introdotto SELECT From INSERT Il DB2 V9 ha aggiunto SELECT From MERGE, UPDATE, DELETE ◦ FROM data-change-table-reference A.Sironi 2014 61 SELECT FROM INSERT ◦ Già disponibile con il DB2 V8 Esempio SELECT id, qty_on_hand, upsert_ts, row_nr FROM FINAL TABLE (INSERT INTO items ( id, qty_on_hand) INCLUDE (row_nr SMALLINT) VALUES (101, 100, 1) ,(102, 200, 2)) ORDER BY row_nr; A.Sironi 2014 62 31 4/19/2014 SELECT FROM UPDATE SELECT id, qty_on_hand, upsert_ts FROM FINAL TABLE (UPDATE SET , WHERE items qty_on_hand = qty_on_hand + 100 upsert_ts = current timestamp id = 12345) ; SELECT FROM DELETE SELECT id, qty_on_hand, upsert_ts FROM OLD TABLE (DELETE FROM items WHERE id = 12345) ; A.Sironi 2014 63 SELECT * FROM FINAL TABLE ( MERGE INTO items AS T USING (VALUES (:item_id, :qty)) AS N(id, qty) ON T.id = N.id WHEN MATCHED THEN UPDATE SET qty_on_hand = T.qty_on_hand + N.qty, T.upsert_ts = current timestamp WHEN NOT MATCHED THEN INSERT (id, qty_on_hand, upsert_ts) VALUES (N.id, N.qty, current timestamp) ) A.Sironi 2014 64 32 4/19/2014 TRUNCATE table ◦ Un’alternativa efficace ed efficiente a DELETE FROM table LOAD REPLACE con input vuoto (dummy) ◦ Ise la tabella è una base table, vengono TRUNCATEd anche eventuali porzioni di tipo LOB e XML, e tutti gli indici associati Sintassi A.Sironi 2014 65 DROP STORAGE (default) ◦ Tutto lo spazio disco assegnato alla tabella viene liberato e reso disponibile alla medesima tabella o ad altre tabelle residenti nel medesimo Tablespace REUSE STORAGE ◦ Tutto lo spazio disco assegnato alla tabella viene svuotato, ma continua ad essere asegnato alla tabella IGNORE DELETE TRIGGERS (default) RESTRICT WHEN DELETE TRIGGERS ◦ Auto-esplicativo ◦ Restituisce un errore se sulla tabella è definito almeno un Trigger di Delete IMMEDIATE ◦ ROLLBACK non ha effetto; se omesso, in caso di ROLLBACK viene ripristinata la situazione iniziale A.Sironi 2014 66 33 4/19/2014 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 67 Temporary Table ◦ Utili quando si ha la necessità di memorizzare delle informazioni solo per la durata della transazione Due tipi di Temporary Table ◦ CGTT (C Created Global Temporary Table) No logging, no locking ◦ DGTT (D Declared Global Temporary Table) «Limited logging», «limited locking» A.Sironi 2014 68 34 4/19/2014 Caratteristiche e limiti ◦ Definizione tramite comando CREATE GLOBAL TEMPORARY TABLE No valori di default diversi da NULL No LOB o ROWID Nessun tipo di constraint (Ref. Integrity, ecc,) ◦ ◦ ◦ ◦ ◦ ◦ Struttura condivisa No logging No locking Nessuna possibilità di definire indici Update non permessi Delete permessi solo se privi della clausola WHERE Istanziazione ◦ Copia privata istanziata al primo riferimento da uno statement SQL di Delete, Insert, SELECT o OPEN Cursor A.Sironi 2014 69 Commit ◦ If no pending «WITH HOLD» open cursor, all rows of every temporary table of the application process are deleted If also RELEASE(COMMIT) in effect, all logical work files for every temporary table are also deleted Rollback ◦ all rows and all logical work files of every temporary table of the application process are deleted. A.Sironi 2014 70 35 4/19/2014 Uso ◦ Quando si ha necessità di memorizzare dati solo per la durata di un processo applicativo e non si ha necessità di condividere la struttura della tabella Definizione ◦ Tramite comando DECLARE GLOBAL TEMPORARY TABLE L’istanza è nota solo all’applicazione che l’ha definita La definizione non è memorizzata nel Catalogo DB2 ed esiste solo finchè è attivo il pocesso applicativo che l’ha creata Implicitamente (o esplicitamente) qualificata con SESSION Istanziazione ◦ Una copia vuota quando viene eseguito il comando DECLARE GLOBAL TEMPORARY TABLE A.Sironi 2014 71 Opzioni di COMMIT ◦ DELETE ROWS Applicata se nessun cursore con WITH HOLD è aperto sulla DGTT ◦ PRESERVE ROWS ◦ DROP TABLE Applicata se nessun cursore con WITH HOLD è aperto sulla DGTT Molti meno vincoli rispetto alle CGTT ◦ ◦ ◦ ◦ ◦ Colonne con valori di default Possibilità di definire indici Supporto di UPDATE e DELETE con predicati Supporto di SAVEPOINT Ecc. A.Sironi 2014 72 36 4/19/2014 Definizione Created GTT Declared GTT DBA tramite CREATE Utente tramite DECLARE Memoria nel Catalogo Si No Valori di default Solo NULL Si Colonne LOB e ROWID Non permesse Permesse Struttura Condivisa Non condivisa Logging No Limitato Locking No Limitato Definizione di indici Non permessa Permessa SQL Update Non permesso Permesso SQL Delete Solo senza WHERE Permesso Supporto SAVEPOINT No Si Opzioni di Commit Nessuna - righe DELETE / PRESERVE ROWS cancellate in assenza di DROP TABLE cursore WITH HOLD aperto A.Sironi 2014 73 Statement SQL: Costi di riferimento EXPLAIN: Prevenire è meglio che curare Ricerche generiche: Tecniche da evitare e loro alternative NULL: Uso e abuso Architettura Batch e ottimizzazioni ◦ Multi Multi-row Fetch / multimulti-row Insert ◦ Query Parallelism ◦ Ricerca binaria (aka (aka dicotomica) Ulteriori ottimizzazioni dei consumi di CPU ◦ Fetch 1 Row Only; Only; Optimize For 1 Row ◦ Temporary Table ◦ Extended Indicator Variable A.Sironi 2014 74 37 4/19/2014 Il dilemma degli sviluppatori ◦ Come predisporre del codice capace di gestire tutte le operazioni di UPDATE e INSERT di una tabella, non sapendo fino al momento dell’esecuzione quali colonne inserire o aggiornare. Tutti gli approcci in uso sono insoddisfacenti ◦ Costruzione dinamica dello statement SQL ◦ Codifica in anticipo di tutte le possibili combinazioni di statement SQL ◦ Codifica di un unico statement SQL in grado di gestire tutte le possibili combinazioni di colonne A.Sironi 2014 75 Permette di specificare 1. Che per una o più colonne oggetto di Insert, Update o Merge non viene fornito nessun valore 2. Come il DB2 deve trattare i valori mancanti L’uso può essere abilitato ◦ A livello del Package, tramite l’opzione EXTENDEDINDICATOR dei comandi BIND e REBIND PACKAGE ◦ Per l’SQL dinamico, tramite l’attributo “WITH EXTENDED INDICATORS” dello statement PREPARE NOTE ◦ L’impostazione modifica iil risultato dell’esecuzione dello statement SQL A.Sironi 2014 76 38 4/19/2014 Quando un’Indicator Variabile è usata in input, il valore assegnato condiziona il comportamento del DB2, come segue: ◦ -5 Valore di Default, se Extended Indicator Variable abilitata NULL, in caso contrario ◦ -7 Non impostata (= come se non presente nello statement), se Extended Indicator Variable abilitata NULL, in caso contrario ◦ -1, -2, -3, -4, or -6 NULL ◦ 0 o qualunque valore positivo La variabile contiene un vaore valido I valori diversi da -1 non vengono assegnati dal DB2 a (Extended) Indicator Variable usate in output A.Sironi 2014 77 Per INSERT ◦ I valori -5 e -7 conducono allo stesso risultato, perché la semantica dell’Insert è quella di impostare la colonna a NULL o inserire un valore di default (a seconda della definizione adottata) per ogni colonna alla quale non è stato assegnato un valore Per UPDATE o MERGE UPDATE ◦ Il valore -5 provoca l’aggiornamento della colonna al valore di default ◦ Il valore -7 fa sì che la colonna non venga aggiornata A.Sironi 2014 78 39 4/19/2014 A.Sironi 2014 79 Fetch 1 Row Only; Only; Optimize For 1 Row MultiMulti-row Fetch / multimulti-row Insert Query Parallelism Ricerca binaria (aka (aka dicotomica) Nuovi costrutti SQL Generazione di Chiavi di Univocità: Oggetto SEQUENCE ◦ Temporary Table ◦ Stored Procedure ◦ Extended Indicator Variable ◦ ◦ ◦ ◦ ◦ Intervalli di Validità e SQL “Temporal “Temporal Support” Support” A.Sironi 2014 80 40 4/19/2014 Permette di reperire più righe dell’answer dell’answer set con una sola Fetch Garantisce un miglioramento significativo delle prestazioni, specialmente per applicazioni DRDA ◦ Un solo viaggio in rete (on in Cross-Memory, se locale) ◦ Quando si devono reperire o inserire grandi quantità di dati ◦ La Distributed Block Fetch aveva già permesso di migliorare il costo di alcune FETCH, ma non delle INSERT ◦ Possibile sostanziale riduzione del consumo di CPU anche per applicazioni non-DRDA Richiede la definizione di array nei programmi ◦ FETCH verso un array, oppure … ◦ INSERT da un array Posizionamento al Rowset usato per‘navigare’ per‘navigare’ A.Sironi 2014 81 ROWSET ◦ Un gruppo di righe restituito da una singola operazione di FETCH ◦ Abilitato sulla dichiarativa del Cursore EXEC SQL DECLARE C1 CURSOR WITH ROWSET POSITIONING FOR SELECT * FROM EMP; ◦ Dimensione del set dichiarata dal programma sulla Fetch FETCH FIRST ROWSET FROM C1 FOR x ROWS INTO ... Dimensione massima: 32,767 righe ◦ Posizionamento del ROWSET (pagine successive) ◦ Nell’uso di un cursore multi-row, il programma può mescolare Fetch di una sola riga con Fetch multi-row A.Sironi 2014 82 41 4/19/2014 Fetch delle PRIME 100 righe FETCH FIRST ROWSET FROM C1 FOR 100 ROWS INTO ... Fetch delle 50 righe SUCCESSIVE partendo dalla posizione corrente del cursore FETCH ROWSET FROM C1 FOR 50 ROWS INTO ... Fetch del ROWSET precedente FETCH PRIOR ROWSET FROM C1 FOR 50 ROWS INTO ... Fetch di 20 Righe a partire dalla Riga 10 FETCH ROWSET STARTING AT ABSOLUTE 10 FROM C1 FOR 20 ROWS INTO ... Quando la Fetch restituisce un numero di righe inferiore a quanto righiesto, righiesto, il DB2 restituisce le righe rimaste insieme all’SQLCODE +100 A.Sironi 2014 83 La multimulti-row Fetch richiede l’uso di array di variabili host ◦ Tutti gli elementi di un array contengono un valore proveniente dala medesima colonna ◦ Gli array possono essere referenziati solo da una multirow FETCH o da una multi-row INSERT ◦ In generale, gli array non possono essere array di strutture Esempio Cobol: 01 OUTPUT-VARS. 05 LASTNME OCCURS 10 TIMES. 49 LASTNME-LGTH PIC S9(4) USAGE COMP. 49 LASTNME-DATA PIC X(50). 05 EMPNO PIC S9(9) COMP-4 OCCURS 10 TIMES. ……….. EXEC SQL FETCH FIRST ROWSET FROM C1 FOR 10 ROWS INTO :LASTNME, :EMPNO A.Sironi 2014 84 42 4/19/2014 Dopo l’esecuzione di una multimulti-row FETCH, il cursore è posizionato su TUTTE le righe del ROWSET corrente Aggiornamento/cancellazione Aggiornamento/cancellazione dell’intero ROWSET UPDATE T1 SET C1 = 5 WHERE CURRENT OF CURSOR1 DELETE FROM T1 WHERE CURRENT OF CURSOR1 Aggiornamento/cancellazione Aggiornamento/cancellazione di una specifica riga del ROWSET UPDATE T1 SET C1 = 5 WHERE CURRENT OF CURSOR1 FOR ROW 4 OF ROWSET DELETE FROM T1 WHERE CURRENT OF CURSOR1 FOR ROW 4 OF ROWSET A.Sironi 2014 85 E’ stata misurata una riduzione del consumo di CPU fino al 50% ◦ Il guadagno ottimale si ha a circa 100 righe per Fetch Il beneficio si riduce con un elevato numero di colonne ◦ Guadagno trascurabile con meno di 10 righe per Fetch MultiMulti-Row Fetch con DSNTIAUL V8 e versioni successive ◦ Nuovo default: 100 Righe per Fetch L’utente Uspuò impostare un valore diverso ◦ Molto probabile una riduzione del consumo di CPU di circa il 50% quando si rperiscono milioni di righe A.Sironi 2014 86 43 4/19/2014 Per determinare quante righe sono state aggiornate da uno statement di UPDATE Per gestire una molteplicità di errori SQL durante una Insert NOT ATOMIC multimulti-row ◦ GET DIAGNOSTICS :rcount = ROW_COUNT; ◦ GET DIAGNOSTICS :numerrors = NUMBER; ◦ Poi, si proceda con un loop per eseguire lo statement che segue per il numero degli errori GET DIAGNOSTICS CONDITION :i :retstate = RETURNED_SQLSTATE Per reperire tutte le infromazioni diagnostiche disponibili per uno statement SQL ◦ GET DIAGNOSTICS :diags = ALL STATEMENT ◦ Esempio di output in :diags Number=1; Returned_SQLSTATE=02000; DB2_RETURNED_SQLCODE=+100; Vengono restituite ulteriori informazioni per tutti gli elementi applicabili e tutte le condizioni I vari elementi sono separati da un punto e virgola A.Sironi 2014 A.Sironi 2014 87 88 44 4/19/2014 [1] SG24-7892 DB2 10 for z/OS Technical Overview, Overview December 2010 [2] SG24-7942 DB2 10 for z/OS Performance Topics, Topics June 2011 [3] IBM DB2 for z/OS Best Practices Web Page at www.ibm.com/developerworks/data/bestpractices/db2zos/ [4] Adrian Collett, Need to Cut Costs? Time to Go Parallel on a zIIP? zIIP? , http://www.idug.org/p/cm/ld/fid=97&tid=88&stid=92 A.Sironi 2014 89 45
© Copyright 2024 ExpyDoc