Inhaltsverzeichnis

Statistiken anlegen und überwachen

1. Systemweite Statistik

In der DOAG News 01/2013 (S.52) ist ein sehr gut gemachter Artikel von Thorsten W. Grebe über die Problematik mit den Oracle Systemstatistiken zu finden: “Glücksspiel Systemstatistiken - Das Märchen vom typischen Workload“.

Unter diesen Link ist sein Vortrag zu dem Thema auf der DOAG Konferenz: DOAG_Nuenberg_2012_Gluecksspiel_Systemstatistiken.

A) NoWorkload Statisik anlegen für eine neue DB Installation

Überwachen mit:

column sname format a20
column pname format a20
column pval2 format a20
SELECT
 sname
 , pname
 , pval1
 , pval2
 FROM
sys.aux_stats$;

Mit dem PL/SQL Package dbms_stats wird eine erste Workload Statistik angelegt.

SET timing ON
exec DBMS_STATS.gather_system_stats();

siehe auch Statistik 10g

B) Workload Statisik anlegen für eine laufende DB Installation

Start während der laufenden Arbeitszeit

EXECUTE DBMS_STATS.gather_system_stats('Start');   

Stoppen ca. 1h später

EXECUTE DBMS_STATS.gather_system_stats('Stop');

C) Statistiken für das Data Dictionary anlegen

Für eine komplett neue Statistik der DB bei Bedarf zuvor löschen

SET timing ON
Exec DBMS_STATS.DELETE_DATABASE_STATS;
Exec DBMS_STATS.DELETE_DICTIONARY_STATS;
Exec DBMS_STATS.DELETE_FIXED_OBJECTS_STATS;

Neue Statisik anlegen

Data Dictionary analysieren
degree Parameter = Anzahl Prozessoren der Maschine

SET timing ON
exec DBMS_STATS.gather_fixed_objects_stats(NULL);
exec DBMS_STATS.GATHER_DICTIONARY_STATS (estimate_percent  => 100, degree  => 24,options  => 'GATHER')
--

D) Statistiken für die einzelnen Schemas

Zum Schluss über allen noch nicht analysierten Objekte

CONNECT / AS sysdba
-- prüfen was wann analysiert wurde
SELECT TO_CHAR(LAST_ANALYZED,'dd.mm hh24'),owner,COUNT(*) FROM dba_tables GROUP BY owner,TO_CHAR(LAST_ANALYZED,'dd.mm hh24') ORDER BY 1 DESC;
SET timing ON
-- ein Schema
Exec DBMS_STATS.GATHER_SCHEMA_STATS ( ownname => 'MEIN_USER',degree=>24,options=>'GATHER AUTO' );
-- Alles in der DB das nicht analysiert wurde
Exec DBMS_STATS.GATHER_DATABASE_STATS (degree=>24,options=>'GATHER AUTO' );

Statistik exportieren / importieren

Ziel: Aus der Produktion die gleiche Statisik in das Testsystem kopieren

-- prüfen of die Tabelle schon da ist/war
 
sqlplus / AS sysdba
 
sqlplus>SELECT owner,TABLE_NAME FROM dba_tables WHERE TABLE_NAME='EXPSTATSTABLE'
 
-- falls existiert löschen 
 
EXEC dbms_stats.drop_stat_table(ownname => 'SYS', stattab => 'EXPSTATSTABLE');
 
-- Tabelle für die Statistiken anlegen
EXEC dbms_stats.create_stat_table  (ownname => 'SYS', stattab => 'EXPSTATSTABLE', tblspace => 'sysaux'); 
 
 
-- Kopieren der Statistik der DB in die Tabelle
 
-- Exportieren der Statistiken der ganzen Datenbank
EXEC dbms_stats.EXPORT_DATABASE_STATS (statown => 'SYS'   , stattab => 'EXPSTATSTABLE',statid =>'SB5MEGAPATCH' );
-- oder alternativ die eines Anwendres
-- Exportieren der Statistiken des Eigentümers der Schema Objekte
-- exec dbms_stats.export_schema_stats(ownname => 'OPERATOR' , stattab =>'EXPSTATSTABLE' ,statid =>'OB5MEGAPATCH',statown => 'sys');
 
--  prüfen ob Einträge vorhanden sind ( 11g >> 92000! für eine leere Datenbank! )
SELECT COUNT(*) FROM EXPSTATSTABLE;
 
--
exit

Export der Tabelle in einen Dump file

exp "'sys as sysdba'" file=prod_stats.dmp tables=EXPSTATSTABLE rows=yes 

Importieren der Tabelle im Zielsystem

imp "'sys as sysdba'" file=prod_stats.dmp tables=EXPSTATSTABLE ignore=yes

Löschen der bestehenden Statistik bei Bedarf

sqlplus / AS sysdba
EXEC dbms_stats.delete_database_stats(no_invalidate =>TRUE ,stattype => 'ALL',force => TRUE);
 
-- oder alternativ nur für einen Anwender
-- exec dbms_stats.delete_schema_stats ( ownname => 'OPERATOR' );  

Importieren der Statisik

-- import DB statistic
EXEC dbms_stats.import_database_stats(stattab =>'EXPSTATSTABLE' ,statid =>'SB5MEGAPATCH',statown =>'SYS' ,no_invalidate => TRUE,force => TRUE); 
 
-- import schema statistic bei Bedarf
-- exec dbms_stats.import_schema_stats ( ownname => 'OPERATOR', stattab =>'EXPSTATSTABLE' , statid =>'OB5MEGAPATCH', statown  => 'SYS',no_invalidate => TRUE,force => TRUE); )
 
 
-- evtl. gecached Information aus der SGA entfernen
ALTER system FLUSH shared_pool;

Histogramme auf Tabellen Spalten vermeiden

Wenn keine Histogramme auf den Tabellen Spalten gewünscht sind mit method_opt ⇒ 'FOR ALL COLUMNS SIZE 1' die Erstellung deaktivieren.

Beispiel für eine Tabelle, in 10g muss die Statistik aber komplett gelöscht werden (10g) , ab 11g kann mit dbms_stats.delete_column_stats direkt das Histogramm einer Spalte gelöscht werden.

BEGIN
 
dbms_stats.delete_table_stats(
      ownname=>'SCOTT'
    , tabname=>'EMP'
    , no_invalidate => FALSE);
);
 
dbms_stats.gather_table_stats ( 
      ownname          => 'SCOTT' 
     ,tabname          => 'EMP'
     ,estimate_percent => dbms_stats.auto_sample_size 
     ,method_opt       => 'FOR ALL COLUMNS SIZE 1' 
     ,cascade          => TRUE 
     ,degree           => 8 
);
 
END;
/

Best Practices for Gathering Optimizer Statistics

Script für die Überwachung

stat.sql
SET linesize 130
 
ttitle left  "Workload Statistik Values" skip 2
 
column SNAME format a20
column pname format a15
column PVAL2 format a20
 
SELECT SNAME,
 PNAME,
 PVAL1,
 PVAL2 FROM sys.aux_stats$
/
 
ttitle left  "LAST ANALYZED Tables Overview" skip 2
 
SELECT TO_CHAR(LAST_ANALYZED,'dd.mm hh24')
       ,owner,COUNT(*)  
  FROM dba_tables 
 GROUP BY owner,TO_CHAR(LAST_ANALYZED,'dd.mm hh24') 
 ORDER BY 1 DESC;
 
ttitle off

siehe auch statistic.sql für die aktuellste Version.

Quellen

Blogs:

Vorträge:

Doku: