Seite 1
SQL-Analyse und Tuning Einfach und schnell Thorsten Bruhns Solution Architekt OPITZ CONSULTING Deutschland GmbH Standort Bad Homburg Mannheim, 27.09.2012 Seite 2
Agenda 1. Einleitung 2. Herausforderungen beim SQL-Tuning 3. SQL-Planermittlung 4. Fazit Seite 3
1 Einleitung Seite 4
Einleitung Klassifikation des Problems Systemsetup Hardware, OS, RDBMS, Parametrisierung Applikationsdesign / SQL-Ausführung Langsame SQL-Statements, ungünstige Schleifenverarbeitungen etc. Erfahrungsgemäß ist Applikationsdesign die häufigste Ursache Mehr als 90% der Performance holt man in der Applikation heraus, sofern das Systemsetup vernünftig ist => Das Systemsetup muß passen, jedoch nicht perfekt sein Seite 5
Einleitung einfaches Installationsbeispiel Installation Hardware, OS, Oracle Software DB anlegen, DB Konfigurieren/Parametrisieren Applikation installieren/konfigurieren 1. Tests Gibt es extreme Auffälligkeiten? Paßt das Systemsetup zu den erwarteten Kennzahlen? Fallen schon bestimmte Statements in Auswertungen auf? Anpassungen am Setup von Hardware, OS, Oracle Software 2. Tests Applikationstuning Seite 6
Einleitung Regeln für Tuning Tuningziel sollte immer meßbar sein Immer nur das Tunen was auch spürbare Performancegewinne erzielt Tuning hört auf, wenn gewünschtes Ziel erreicht ist Dieser Vortrag wird sich mit SQL-Statements beschäftigen! Seite 7
2 Herausforderungen beim SQL- Tuning Seite 8
Herausforderungen beim SQL-Tuning Identifikation der SQLs kann anspruchsvoll sein Wer ist denn der top-consumer? Wie sieht denn der Ausführungsplan aus? Was muß denn getunt werden? Was tun, wenn die Applikation massenhaft SQLs ohne Bind-Variablen nutzt? Statspack/AWR liefern hier u. U. falsche top Consumer Was fachlich zusammen gehört, kann technisch nicht gemeinsam betrachtet werden experimentell kann cursor_sharing=force helfen SQL-Trace generiert u. U. sehr viel Tracedaten kann im Handling unangenehm werden => Identifikation kann viel Zeit in Anspruch nehmen keine kostenlose Universallösung bekannt Seite 9
Herausforderungen beim SQL-Tuning Ist es wirklich immer so schlimm? Nein, häufig sind die problematischen Statements identifiziert Fragen an den Entwickler können hilfreich sein Ist Dir das Statement schon mal aufgefallen? Hast Du das mal direkt in SQLPlus getestet? Was tun, wenn man der Entwickler ist und kein DBA greifbar ist? Hoffentlich kennt man das problematische Statement Statspack/AWR sind kein Hexenwerk leicht bedienbar und bieten schnellen Überblick bzw. liefern durchaus gute Ansatzpunkte selbst bei fehlenden Bind-Variablen. SQL-Trace gezielt gut einsetzbar Bei Connection-Pool in Application-Server kann es ätzend werden Testhalber den Pool auf 1 Connection begrenzen Seite 10
3 SQL-Planermittlung Seite 11
SQL-Planermittlung Aktuelle Session Plan für letztes Statement in aktueller Session leicht ermittelbar select * from table(dbms_xplan.display_cursor(null,null,'allstats LAST')) set serverout off vor der Ausführung des Statements erforderlich! Statement isoliert explain plan for select * from emp; select * from table(dbms_xplan.display()); Das können mittlerweile alle üblichen Tools Tipp für DBMS_XPLAN Ein paar Parameter im SQLPlus liefern übersichtliche Ausgaben set pages 2000 lines 200 column PLAN_TABLE_OUTPUT format a200 Seite 12
SQL-Planermittlung andere, bekannte Session Einfach die Session identifizieren und open cursor betrachten: Ermittlung der sql_id ist ein wesentlicher Schritt Dient an vielen Stellen als eindeutiger Schlüssel für Informationen im Shared-Pool select /*+rule*/ sql_id, buffer_gets, DISK_READS, round(cpu_time/1000) cput_ms, executions, to_char(last_active_time, 'DD.MM HH24:MI:SS') lasttime, sql_text from ( select voc.sql_id, vs.version_count, vs.buffer_gets, vs.disk_reads, vs.cpu_time,vs.executions,vs.last_active_time, voc.sql_text sql_text from GV$OPEN_CURSOR voc join V$SQLAREA_PLAN_HASH vs on vs.sql_id = voc.sql_id where voc.sid= &1 and LAST_ACTIVE_TIME is not null order by last_active_time desc) where rownum < 50ord er by executions ohne Hint gibt es manchmal lange Antwortzeiten Achtung! Recursive SQLs von Oracle werden hier mit angezeigt Seite 13
Herausforderungen bei Planermittlung Beispiel für open_cursors SQL_ID BUFFER_GETS DISK_READS CPUT_MS EXECUTIONS LASTTIME SQL_TEXT ------------- ------------ ------------ ---------- ---------- -------------- ---------------------------------------- 6bt4v0wb48k1p 178 13 41 21 25.09 21:32:48 SELECT * FROM CFG_DB_LINKS WHERE ENABLED =1 7vv84sf0ygu26 556 21 35 53 25.09 21:32:48 INSERT INTO WB_RT_NOTIFICATION_ACKS ( AU DIT_ID, STREAM_ID, A 8u5p4pa0kfmdk 1432 33 47 224 25.09 21:32:48 SELECT SERVICE_STOP_PENDING FROM WB_RT_S ERVICE_CONTROL_FLAGS aq8yqxyyb40nn 2933 2 901 710 25.09 21:32:48 update sys.job$ set this_date=:1 where j ob=:2 Recursives SQL meist durch kleingeschriebene Schlüsselwörter erkennbar Kann ignoriert werden, da wir damit leben müssen Top-Consumer über Buffer_gets/Executions oder Disk_reads/Executions oder CPUT_MS/Executions erkennbar Gelieferte Informationen kommen aus dem Shared-Pool Statistische Daten beziehen sich auf alle Ausführungen nicht auf die aktuelle Session! Was sind denn Top-Consumer? Seite 14
Top-Consumer Was sind denn Top-Consumer? DB-Time für einzelnes Statement sehr groß DB-Time = CPU Time + Wait Time CPU Time üblicherweise parse time + lesen im Cache (consisten gets Wait Time normalerweise physischer I/O Top-Consumer können nun über open_cursor bewertet werden Das geht natürlich auch über v$sqlarea Statspack/AWR ermitteln so die Top-Consumer nach verschiedenn Kriterien Seite 15
Ausführungspläne Was sagt uns der Ausführungsplan? Beschreibt die Ausführungsstrategie der SQL-Engine Wird vom Optimizer mit Hilfe von statistischen Informationen berechnet Statistik und Realität passen manchmal nicht zusammen Kosten dienen intern zum Vergleich verschiedener Pläne Plan mit geringsten Kosten entspricht dem tatsächlichen Ausführungsplan explain plan for select count(1) from perfstat.stats$snapshot; select * from table(dbms_xplan.display()) Plan hash value: 3157580645 ----------------------------------------------------------------------------------- Id Operation Name Rows Cost (%CPU) Time ----------------------------------------------------------------------------------- 0 SELECT STATEMENT 1 5 (0) 00:00:01 1 SORT AGGREGATE 1 2 INDEX FAST FULL SCAN STATS$SNAPSHOT_PK 3201 5 (0) 00:00:01 ----------------------------------------------------------------------- Seite 16
gather_plan_statistics Kann man Plan und Realität gegenüber stellen? Ja, das geht ganz einfach: set serverout off select /*+gather_plan_statistics*/ count(1) from perfstat.stats$snapshot; select * from table(dbms_xplan.display_cursor(null,null,'allstats LAST')) ----------------------------------------------------------------------------------------------------- Id Operation Name Starts E-Rows A-Rows A-Time Buffers ----------------------------------------------------------------------------------------------------- 0 SELECT STATEMENT 1 1 00:00:00.01 76 1 SORT AGGREGATE 1 1 1 00:00:00.01 76 2 INDEX FAST FULL SCAN STATS$SNAPSHOT_PK 1 3201 3305 00:00:00.01 76 ----------------------------------------------------------------------------------------------------- E-Rows = Vorhersage Optimizer A-Rows, A-Time (DB Time) = tatsächliche Werte für die Ausführung Buffers = verarbeitete Blöcke Gut erkennbar, wo die DB Time verbrannt wird! Seite 17
Ausführungspläne weitere Details Ausführungspläne enthalten noch mehr Daten Filterpredicate beschreiben, wie die SQL-Engine wo filtert Indexnutzung sinnvoll? Falscher Index => möglicherweise zu viele Treffer in A-Rows mit anschließenden Tabellenzugriff => große DB Time wegen großer Blockanzahl (A-Time) Viele Tools zeigen mittlerweile auch Filter bei Ausführungsplänen mit an -------------------------------------------------------------------------------------------------------------- Id Operation Name Starts E-Rows A-Rows A-Time Buffers OMem -------------------------------------------------------------------------------------------------------------- 0 SELECT STATEMENT 1 1 00:00:00.08 16 1 SORT AGGREGATE 1 1 1 00:00:00.08 16 2 MERGE JOIN 1 278 475 00:00:00.07 16 3 INDEX FULL SCAN STG_DBI_PK_PK_1 1 7 6 00:00:00.03 1 * 4 SORT JOIN 6 79 475 00:00:00.04 15 73728 * 5 TABLE ACCESS FULL DWH$SNAPSHOT 1 79 95 00:00:00.02 15 Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("si"."dbid"="ss"."dbid") filter("si"."dbid"="ss"."dbid") 5 - filter("ss"."startup_time">sysdate@!-4) Seite 18
Fazit Finden der Top-Consumer manchmal schwierig Mit passender Strategie eigentlich kein Problem DB Time ist der Schlüssel für Performance gather_plan_statistics-hint sehr praktisch Liefert schnell Informationen über das was Oracle tatsächlich macht Verursacher in umfangreichen Selects schnell identifizierbar Für 1. Analyse keine Kenntnisse über das Datenmodell benötigt Filterregeln sehr hilfreich Was passiert mit der DB Time, wenn ich Hints einsetze? SQL-Analyse ist kein Hexenwerk geht einfacher als häufig vermutet Seite 19
Fragen und Antworten Seite 20
Kontakt Thorsten Bruhns Solution Architekt OPITZ CONSULTING Deutschland GmbH Standort Bad Homburg Norsk-Data-Strasse 2 51647 Bad Homburg Tel. +49 (6172) 6626 0 0 thorsten.bruhns@opitz-consulting.com Seite 21