Johannes Ahrends CarajanDB GmbH www.CarajanDB.com © 2013 CarajanDB GmbH • CarajanDB • Warum ist eine Anwendung langsam? • Beispiele von „echten“ Performanceproblemen 2 www.CarajanDB.com © 2013 CarajanDB GmbH • Experten mit über 20 Jahren Oracle Erfahrung • Firmensitz in Erftstadt bei Köln • Spezialisten für • Oracle Datenbank Administration • Hochverfügbarkeit (RAC, Data Guard, Failsafe, etc) • Einsatz der Oracle Standard Edition • Oracle Migrationen (HW, Unicode, Konsolidierung, Standard Edition) • Replikation (Goldengate, SharePlex, Dbvisit) • Performance Tuning • Schulung und Workshops (Oracle, Toad) 3 www.CarajanDB.com © 2013 CarajanDB GmbH • Ungünstig programmiert • Verarbeitung zu aufwändig • Es werden zu viele Daten gelesen • Datenverarbeitung zu langsam • Datenselektion zu aufwändig • Änderung der Daten zu kompliziert • Datenbank zu langsam • Unterdimensionierte Hardware • Zu viel Last • Falsch konfigurierte Datenbank 4 www.CarajanDB.com © 2013 CarajanDB GmbH • Subjektive Ursachen • Schlechtes Wetter • Persönliche Probleme • Neue Softwareversion „Früher war alles besser“ • Objektive Ursachen • Datenmenge hat zugenommen • Fehler durch Batchverarbeitung • Falscher Ausführungsplan • Falsche Statistiken 5 www.CarajanDB.com © 2013 CarajanDB GmbH • Forrester Research 6 www.CarajanDB.com © 2013 CarajanDB GmbH www.CarajanDB.com © 2013 CarajanDB GmbH 1. Parsen der Anweisung • Ermitteln, ob identische Anweisung bereits im Library Cache vorliegt • Syntax und Semantik der Anweisung prüfen • Evtl. Sperren von verwendeten Objekten • Erstellen des Ausführungsplans und Abspeichern im Library Cache 2. Ausführen • ausgewählte Zeilen ermitteln 3. Abrufen • Ermitteln, ob betroffene Elemente bereits im Database Buffer Cache vorliegen • ggfs. Daten aus den Datenfiles in den Database Buffer Cache laden • zurückgeben der Daten an den Benutzer-Prozess 8 www.CarajanDB.com © 2013 CarajanDB GmbH 1. Parsen der Anweisung • • • • Ermitteln, ob identische Anweisung bereits im Library Cache vorliegt Syntax und Semantik der Anweisung prüfen Evtl. Sperren von verwendeten Objekten Erstellen des Ausführungsplans und Abspeichern im Library Cache 2. Ausführen • • • • • Lesen der Daten (aus Undo-Segmenten, Database Buffer Cache oder Datenfiles) Sperren auf zu ändernde Zeilen setzen Protokollieren der Änderungen im Redolog Buffer Erstellen des "Before Image" im Undo Segment und Änderung an den Originaldaten im Database Buffer Cache vornehmen „Before Images“ ebenfalls im Redolog Buffer protokollieren Markieren der geänderten Blöcke als "dirty" 9 www.CarajanDB.com © 2013 CarajanDB GmbH • Wiederverwendung von Befehlen • Parsen wird eingespart • Gleicher Ausführungsplan • Nur bei identischen Befehlen (gleicher Hash-Value) • Beispiel: • Nicht wiederverwendbar (Literale): SELECT vorname, nachname FROM personen WHERE nachname = 'Meier'; • Wiederverwendbar (Bindevariable): SELECT vorname, nachname FROM personen WHERE nachname = :nachname; • Bindevariablen werden erst zur Laufzeit hinzugefügt 10 www.CarajanDB.com © 2013 CarajanDB GmbH • Über Statistiken werden die Plankosten ermittelt. • Tabellen und Indizes werden überwacht („MONITORING“) und automatisch neu analysiert, wenn sich mehr als 10% der Daten seit der letzten Analyse geändert hat. • Die Statistiken sollten immer aktuell sein! Genutzt werden: • Tabellenstatistiken • Spaltenstatistiken • Indexstatistiken • Systemstatistiken (CPU, Memory, I/O) • Server Parameter (init.ora) 11 www.CarajanDB.com © 2013 CarajanDB GmbH • Der Oracle Optimizer entscheidet aufgrund der Statistiken, auf welche Art das Statement abgearbeitet werden soll. • Es wird ein Ausführungsplan erstellt. Alle beteiligten Objekte und die Reihenfolge der Abarbeitung sind dort beschrieben. • Der Ausführungsplan wird ausgeführt. 12 www.CarajanDB.com © 2013 CarajanDB GmbH • Beinhaltet die Ausführung des Statements • Unterscheidung zwischen: • Ermitteln eines exemplarischen Ausführungsplans „wenn ich diesen Befehl jetzt ausführen würde, was würde für ein Plan benutzt“ Befehl: „explain Plan for“ Tools (Toad, SQL-Developer, Oracle Enterprise Manager) Enthält die Umgebung, unter der ich den Plan aufrufe • Tatsächlicher Ausführungsplan V$SQL_PLAN V$SQL_PLAN_STATISTICS Natürlich nur für bereits ausgeführte Befehle Nur im Cache (ev. über Tools separat abgespeichert) 13 www.CarajanDB.com © 2013 CarajanDB GmbH SQL> @rdbms/admin/UTLXPLS.SQL PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------Plan hash value: 1342056138 --------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 3583 | 328K| 386 (3)| 00:00:05 | |* 1 | HASH JOIN | | 3583 | 328K| 386 (3)| 00:00:05 | |* 2 | HASH JOIN | | 700 | 56700 | 103 (4)| 00:00:02 | | 3 | MERGE JOIN | | 700 | 37800 | 89 (5)| 00:00:02 | | 4 | TABLE ACCESS BY INDEX ROWID| STATUS | 5 | 170 | 2 (0)| 00:00:01 | | 5 | INDEX FULL SCAN | PK_STATUS | 5 | | 1 (0)| 00:00:01 | |* 6 | SORT JOIN | | 700 | 14000 | 87 (5)| 00:00:02 | |* 7 | TABLE ACCESS FULL | AUFTRAEGE | 700 | 14000 | 86 (4)| 00:00:02 | | 8 | TABLE ACCESS FULL | PERSONEN | 10000 | 263K| 14 (0)| 00:00:01 | | 9 | TABLE ACCESS FULL | POSITIONEN | 353K| 4482K| 281 (2)| 00:00:04 | --------------------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------1 - access("A"."AUFID"="PO"."AUFID") 2 - access("P"."PERSID"="A"."PERSID") 6 - access("S"."STATUSID"="A"."AUFSTATUS") filter("S"."STATUSID"="A"."AUFSTATUS") 7 - filter(TO_CHAR(INTERNAL_FUNCTION("A"."AUFDATUM"),'DD.MM.YYYY')='10.08.2007') www.CarajanDB.com 25 Zeilen ausgewõhlt. 14 © 2013 CarajanDB GmbH 15 www.CarajanDB.com © 2013 CarajanDB GmbH 16 www.CarajanDB.com © 2013 CarajanDB GmbH www.CarajanDB.com © 2013 CarajanDB GmbH • Diätdatenbank („Online Abnehmen“) • Neuer Kunde klagt über massive Probleme: • Server mit 16 Cores fast permanent zu 100 % ausgelastet • Grund: Ende Dezember wurde ein neuer „Anwender“ in Betrieb genommen • Administrator beklagt sich bei Facebook mit einigen Screenshots des Servers (!) 18 www.CarajanDB.com © 2013 CarajanDB GmbH • CPU Load Ende 2013 Anfang 2014 19 www.CarajanDB.com © 2013 CarajanDB GmbH • Remote Login mit Teamviewer • Check der wesentlichen Datenbank Parameter • Keine Auffälligkeiten • Ermitteln der derzeitigen Statistikdaten (Statspack) • Anschließend DBA zum Mittagessen geschickt … • Weiterer Snapshot der Statistikdaten 20 www.CarajanDB.com © 2013 CarajanDB GmbH • Index auf einer Tabelle fehlte 21 www.CarajanDB.com © 2013 CarajanDB GmbH SQL> SELECT FROM WHERE AND p.vorname, p.nachname, a.plz, a.ort personen p INNER JOIN adressen a ON (p.persid = a.persid) p.nachname like 'M%' p.vorname = 'Karl-Gustav-Theodor'; • Langsam oder schnell? 22 www.CarajanDB.com © 2013 CarajanDB GmbH • Schnell wenn: • Wenig Datensätze (z.B. Testsystem mit 100 Sätzen) • Indizierung des Vornamens • Langsam wenn: • Viele Datensätze (Produktion!!!) • Indizierung des Nachnamens und Vornamens (Zusammengesetzter Index) 23 www.CarajanDB.com © 2013 CarajanDB GmbH • Neue Anwendung für Krankheitsgruppen • Anwender bemängeln lange Laufzeiten für Anpassung der Daten • Auffällig: SQL> DELETE FROM partner WHERE id=:id; • Persid ist Primärschlüssel! • Langsam oder schnell? 24 www.CarajanDB.com © 2013 CarajanDB GmbH 25 www.CarajanDB.com © 2013 CarajanDB GmbH • Warum werden so viele Datensätze gelesen? • Tabelle „partner“ hat abhängige Datensätze (Master – Detail) • Kein Index auf den Foreign Key: • Table Lock auf die Detail Tabelle, wenn Update auf Primary Key der Master Tabelle • Updates auf den Primary Key sind selten • Index auf Foreign Key nicht erforderlich • Aber: • DELETE FROM Master Tabelle FULL TABLE SCAN auf die Detail Tabelle 26 www.CarajanDB.com © 2013 CarajanDB GmbH • Abfragen der Versichertendaten langsam • Index oder nicht? SQL> CREATE INDEX idx_name ON personen (vorname, nachname); SQL> SELECT anrede, vorname, nachname 2 FROM tuk.personen pe 3 WHERE pe.nachname LIKE 'wei_' 4 AND pe.vorname LIKE 'Martin'; ANRED ----Herr Herr Herr VORNAME -------------------Martin Martin Martin 3 Zeilen ausgewählt. NACHNAME -------------------Weiß Weis Weiz 2_abfrage_ls.bat 27 www.CarajanDB.com © 2013 CarajanDB GmbH 28 www.CarajanDB.com © 2013 CarajanDB GmbH 29 www.CarajanDB.com © 2013 CarajanDB GmbH • Versuch einer Analyse: SQL> SELECT anrede, vorname, nachname 2 FROM tuk.personen pe 3 WHERE pe.nachname LIKE 'wei_' 4 AND pe.vorname LIKE 'Martin'; ANRED ----Herr Herr Herr VORNAME -------------------Martin Martin Martin NACHNAME -------------------Weiß Weis Weiz 3 Zeilen ausgewählt. 30 www.CarajanDB.com © 2013 CarajanDB GmbH • Versuch einer Analyse: PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------Plan hash value: 1826680655 ------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 25 | 275 (2)| 00:00:04 | | 1 | SORT ORDER BY | | 1 | 25 | 275 (2)| 00:00:04 | |* 2 | TABLE ACCESS FULL| PERSONEN | 1 | 25 | 274 (1)| 00:00:04 | ------------------------------------------------------------------------------Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("PE"."NACHNAME" LIKE 'wei_' AND NLSSORT("PE"."VORNAME",'nls_sort=''BINARY_CI''') =HEXTORAW('6D617274696E00') ) 31 www.CarajanDB.com © 2013 CarajanDB GmbH • ALTER SESSION SET nls_sort=binary_ci; • Sortierung ist unabhängig von Groß- / Kleinschreibung aber abhängig von Akzenten • Alternativen: binary_ai Case und Akzent insensitiv german_ai Deutsche Sortierung, Case und Akzent insensitiv … • ALTER SESSION SET nls_comp=linguistic; • Filter verwenden die gleiche Funktion wie NLS_SORT, d.h. in diesem Fall ist die WHERE- Clausel unabhängig von Groß- / Kleinschreibung und von Akzenten • Alternativen: BINARY oder ANSI 32 www.CarajanDB.com © 2013 CarajanDB GmbH • Entweder Linguistische Suche ausschalten • … oder Index auf Linguistische Suche CREATE INDEX idx_name2 ON personen (NLSSORT (vorname, 'nls_sort=binary_ci'), NLSSORT (nachname, 'nls_sort=binary_ci')); 33 www.CarajanDB.com © 2013 CarajanDB GmbH • Einsatz in der Schweiz Ende 2012 • Anwendung überwacht Mobilfunksender Bei 3000 überwachten Servern ca. 15 Minuten pro Report Bei 9000 überwachten Servern Abbruch des Reports nach 60 Minuten bzw. 80 Minuten Laufzeit Datenbankgröße ca. 20 GByte (5,6 GB Tabellen; 6,5 GB Indizes) 34 www.CarajanDB.com © 2013 CarajanDB GmbH • Statspack Report SQL ordered by Elapsed Time DB/Inst: NCDBP/NCDBP Snaps: 19907-19909 … Elapsed Elapsed Time Time (s) Executions per Exec (s) %Total %CPU %IO SQL Id ---------------- -------------- ------------- ------ ------ ------ ------------3,011.8 1 3,011.85 61.5 98.8 1.1 bx7m7493x4fbu Module: perl.exe SELECT COUNT(DISTINCT h.guid) as host_count, COUNT(DISTINCT fav.app_id) as app_c ount, COUNT(DISTINCT fav.vuln_id) as vuln_count FROM host h INNER JOIN (SELECT h s.guid, NVL(ROUND(AVG(CASE WHEN hs.host_score = 0 THEN NULL ELSE hs.host_score E ND), 0), 0) as host_score, MAX(hs.audit_id) as audit_id, hs.vne_id, hs.host_guid • Elapsed Time: 3.011,8(s) = ca. 50 Minuten 35 www.CarajanDB.com © 2013 CarajanDB GmbH • Abfrage: SELECT COUNT(DISTINCT …) call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------Parse 1 13.87 13.88 0 5 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 1 2962.56 2997.92 29645 966964990 0 1 ------- ------ -------- ---------- ---------- ---------- ---------- ---------total 3 2976.44 3011.81 29645 966964995 0 1 • disk: • query: 29645 = 232 Mbyte 966964995 = 7.399 Gbyte = ca. 7.4 Terabyte (für eine 20 GB große Datenbank) 36 www.CarajanDB.com © 2013 CarajanDB GmbH • Anwendung ursprünglich für SQL-Server geschrieben • Daraus folgt: • SQL-Server standardmäßig Index-Organized-Tabellen • Oracle standardmäßig Heap Tabellen Kein Index auf die abgefragte Spalte 37 www.CarajanDB.com © 2013 CarajanDB GmbH • Nicht zu komplexe Tabellenstrukturen (zu viele Spalten) • Möglichst wenig Änderung in der Tabellenstruktur (ALTER TABLE ADD/DROP COLUMN) • Möglichst immer Primary Key • Foreign Keys benennen und indizieren 38 www.CarajanDB.com © 2013 CarajanDB GmbH • Analysieren der SQL-Befehle • Wird ein Index benutzt • Gibt es die Möglichkeit für zusammengesetzte Indizes • Was ist mit abhängigen Spalten (z.B. Postleitzahl, Ort) • Anwender bei Abfragen „leiten“, um bestimmte, indizierte Spalten zu benutzen • Vermeiden von Full-Table-Scans • Bewusste Verwendung von Variablen und Literalen • Literale bei Spalten mit wenigen Ausprägungen (z.B. Auftragsstatus) • Variablen bei „üblichen“ Spalten (z.B. Vorname, Artikel, …) 39 www.CarajanDB.com © 2013 CarajanDB GmbH • Regelmäßige Health-Checks • Gibt es Tabellen ohne Index • Wie gut ist der Cache ausgelastet • Erstellung von Baselines für kritische SQL-Befehle • Festlegen des Ausführungsplans • Backups zu lastarmen Zeiten planen • Möglich konstante Konfiguration • keine dynamisch veränderbaren Parameter, z.B. sga_target, memory_target • Permanente Performanceüberwachung 40 www.CarajanDB.com © 2013 CarajanDB GmbH • Eine optimale Konfiguration kann nur gelingen, wenn Architekten, Entwickler und Administratoren zusammenarbeiten • „Fingerpointing“ führt zu nichts! 41 www.CarajanDB.com © 2013 CarajanDB GmbH [email protected] www.carajandb.com www.carajandb.com/blogs www.CarajanDB.com © 2013 CarajanDB GmbH