STATSPACK ist ein mit jeder Oracle Datenbank mitgeliefertes, kostenloses Tool zur Auswertung der Performance. Die meisten Datenbank-Administratoren, die schon einmal mit einem Performance-Problem konfrontiert wurden, haben mit Sicherheit einen STATSPACK-Report erzeugt und diesen analysiert. Bitte beachten Sie dass Statspack seit Version 12 kaum bis gar keine Verbesserungen onder Anpassungen bkommen hat und von Oracle nach aktuellen Stand (März 2024) nicht weiterentwicklet wird. Der kostenpflichtige Nachfolger AWR/ADDM steht den Kunden zur Verfügung.
Dieser Tipp setzt Grundwissen in der Benutzung von STATSPACK und SQL vorraus. Falls Sie Hilfe zu STATSPACK benötigen, sollten Sie zuerst diesen Tipp lesen.
Reports über größere Zeiträume und mehrere Snap-IDs hinweg sind sehr ungenau und nicht für eine präzise Analyse geeignet. Wenn man einen einzelnen Wert über den Tag analysieren will und das möglichst detailliert, kann es dazu kommen, dass Sie sehr viele Reports erzeugen und analysieren müssen. Um die Übersicht zu behalten, wird man in der Regel einen Kompromiss eingehen und zum Beispiel nur für jede Stunde einen Report erzeugen.
An sich ist es aber relativ einfach, die benötigten Informationen auf eine übersichtliche Anzahl an Zeilen zu reduzieren.
Der Lösungsansatz dafür ist einfach, jedoch erfordert die Umsetzung mehr Einarbeitung. Alle Daten, die für einen Report verwendet werden, sind in den Tabellen des STATSPACK-Users gespeichert. Das heißt, die Informationen sollten sich ohne Probleme in einem "eigenen" Report anhand von SQL ermitteln lassen.
Mit den zahlreichen Varianten und Möglichkeiten, könnte man wahrscheinlich ein ganzes Buch füllen. Deswegen werden wir uns in diesem Tipp nur mit den Grundlagen, einem einfachen und einem komplexeren Beispiel beschäftigen.
Dieser Tipp soll somit mehr als ein Denkanstoß zur Entwicklung individueller Lösungen, als eine komplette Anleitung aufgefasst werden.
Der Perfstat-User hat um die 70 Tabellen. Die meisten Tabellen haben einen sprechenden Namen, der durchaus Rückschlüsse auf die Inhalte ermöglicht:
SQL> select TABLE_NAME from dba_tables where owner='PERFSTAT';
TABLE_NAME
-------------------------
STATS$LATCH_PARENT
STATS$SNAPSHOT
...
STATS$DATABASE_INSTANCE
STATS$SYSSTAT
.....
STATS$TEMP_SQLSTATS
Die wichtigste Tabelle ist STATS$SNAPSHOT. Sie ist Dreh- und Angelpunkt jedes Selects, da sie SNAP_IDund SNAP_TIME enthält.
Generell ist auch noch zu beachten: Sollte zwischen zwei Snapshots ein Neustart liegen, sind die Daten meist nicht verwendbar.
Am Anfang kann es sich als mühsam erweisen, ein Vorgehen zu entwickeln, wie man grundlegend an die gewünschten Daten gelangt. Hier hilft ein Blick in das Report-Script (befindet sich in der Regel im Oracle Home unter rdbms/admin/spreport.sql). Dort muss man sich dann bis zur entsprechenden Stelle, an der die benötigten Daten abgefragt werden, "durchhangeln" und kann sich dort dann "inspirieren" lassen, wie es diese Daten abzufragen gilt.
Hierzu nun zwei Beispiele:
Mit folgendem Select können Sie einfach ermitteln, wie viele angemeldete User es zum Snapshot-Zeitpunkt auf der Datenbank gab:
SELECT s.snap_time as "Uhrzeit", st.value as "Current Logons" FROM perfstat.stats$snapshot s, perfstat.stats$sysstat st WHERE s.snap_id=st.snap_id and st.name='logons current' ORDER BY s.snap_time;
Die Tabellen STATS$SNAPSHOT und STATS$SYSSTAT werden gejoint und es wird aus der STATS$SYSSTAT Tabelle auf die Werte für 'logons current' eingeschränkt.
Der Output könnte wie folgt aussehen:
Uhrzeit Current Logons ------------------- -------------- 16.06.2016 11:10:57 56 16.06.2016 11:26:20 39 16.06.2016 11:41:25 37 16.06.2016 11:56:30 37 16.06.2016 12:11:35 37 16.06.2016 12:26:41 37 16.06.2016 12:41:46 37 16.06.2016 12:56:51 37 16.06.2016 13:11:56 37 ..... 17.06.2016 09:03:49 36 17.06.2016 09:18:54 47 17.06.2016 09:33:59 36 17.06.2016 09:49:04 35 17.06.2016 10:04:10 36 17.06.2016 10:19:15 52 17.06.2016 10:34:20 36 17.06.2016 10:49:25 36 17.06.2016 11:04:30 36 17.06.2016 11:19:35 99
Aus der Ausgabe könnten Sie zum Beispiel die Peak-Zeiten der Datenbank auslesen, insofern Sie nicht einen App-Server haben, der die Verbindungen poolt. (Connection-Pooling)
Folgender Select ist komplexer und berücksichtigt mehrere Extras, die das einfache Beispiel nicht benötigt:
set linesize 1000 set pagesize 1000 alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS'; col Begintime for a21 heading 'Von' col endtime for a21 heading 'Bis' col fh for 9999999999999 heading 'Failed Parses' col th for 9999999999999 heading 'Total Parses' select * from ( select s.snap_time as begintime, lead(s.snap_time,1, s.snap_time) over (order by snap_time) as endtime, f.fh, t.th from perfstat.stats$snapshot s, ( select snap_id, lead(value, 1, 0) over (order by snap_id)-value as fh from perfstat.stats$sysstat where lower(name)='parse count (failures)' ) f, ( select snap_id, lead(value, 1, 0) over (order by snap_id)-value as th from perfstat.stats$sysstat where lower(name)='parse count (total)' ) t where t.snap_id=s.snap_id and s.snap_id=f.snap_id and t.snap_id=f.snap_id order by s.snap_time) where begintime<>endtime and (fh>=0 or th>=0);
Die Ausgabe könnte wie folgt aussehen:
Von Bis Failed Parses Total Parses --------------------- --------------------- -------------- -------------- 16.06.2016 11:10:57 16.06.2016 11:26:20 6 9030 16.06.2016 11:26:20 16.06.2016 11:41:25 1 4866 16.06.2016 11:41:25 16.06.2016 11:56:30 2 966 16.06.2016 11:56:30 16.06.2016 12:11:35 0 3948 16.06.2016 12:11:35 16.06.2016 12:26:41 0 897 16.06.2016 12:26:41 16.06.2016 12:41:46 0 922 16.06.2016 12:41:46 16.06.2016 12:56:51 0 901 16.06.2016 12:56:51 16.06.2016 13:11:56 0 3362 16.06.2016 13:11:56 16.06.2016 13:27:01 0 894 ... 17.06.2016 09:03:49 17.06.2016 09:18:54 0 921 17.06.2016 09:18:54 17.06.2016 09:33:59 0 893 17.06.2016 09:33:59 17.06.2016 09:49:04 0 944 17.06.2016 09:49:04 17.06.2016 10:04:10 5 4030 17.06.2016 10:04:10 17.06.2016 10:19:15 0 958 17.06.2016 10:19:15 17.06.2016 10:34:20 0 885 17.06.2016 10:34:20 17.06.2016 10:49:25 0 938 17.06.2016 10:49:25 17.06.2016 11:04:30 0 3927 17.06.2016 11:04:30 17.06.2016 11:19:35 0 1015 17.06.2016 11:19:35 17.06.2016 11:34:40 0 11814
Da "Total Parses" und "Failed Parses" kumulativ seit Instanzstart gespeichert werden, muss man hier mit lead oder lag arbeiten, damit man nur die Werte pro Zeitabschnitt erhält. Sollen beide Werte in einer Zeile stehen, werden die entsprechenden Selects in Subselects verpackt.
Failed Parses sind vor allem interessant, um Applikationen zu finden, die zum Beispiel nicht vorhandene Tabellen abfragen (Eine Abfrage auf eine nicht vorhandene Tabelle gibt einen Failed Parse.).
Falls Sie Hilfe bei der Erstellung oder Interpretation benötigen, können Sie sich gerne an uns wenden, wir helfen Ihnen gerne.