Dienstag, 28. April 2009

Index-Optimierung: Einige Grundlagen

Häufige Indexsynchronisierung nach DML Operationen kann zu Indexfragmentierungen führen. Indexfragmentierungen wiederum können dabei die Antwortzeiten der Textabfragen negativ beeinflussen. Weniger häufige Synchronisierungen - also Batchoperation und längere Listen beim Synchronisieren - führen zu weniger Zeilen im Index und daher geringerer Fragmentierung. Häufig hängt allerdings das entsprechende Intervall der Synchronisierung von Anwenderanforderungen ab. Falls Sie mehr Informationen zur Synchronisierung bzw. zur Indexfragmentierung benötigen, schauen Sie einfach in den folgenden Blog. Regelmässige Optimierung ist also wichtige Operation, da die Indexfragmentierung und Indexgröße dabei reduziert werden und somit die Performance der Abfragen erhöht werden kann. Optimiert wird der Index mit der Prozedur CTX_DDL.OPTIMIZE_INDEX, die in unterschiedlichen Modi durchgeführt werden können:
  • FAST: Aufhebung der fragmentierten Zeilen, allerdings keine Optimierung der gelöschten Daten
  • FULL: Aufhebung der fragmentierten Zeilen und Optimierung der gelöschten Daten (Garbage)
  • REBUILD: wie FULL nur dass die $I Tabelle neuaufgebaut wird-u.U. schneller als FULL
  • TOKEN: volle Optimierung einzelner Tokens
  • TOKEN_TYPE: volle Optimierung bezogen auf einen bestimmten Tokentyp

Der Anwender kann auch während einer OPTIMIZE-Operation weitersuchen und einfügen. Je nach Modus kann die OPTIMIZE-Operation allerdings sehr lange dauern, CPU und I/O intensiv sein und somit das ganze System beeinflussen. Daher ist es im Modus FULL möglich die OPTIMIZE-Operation mithilfe des Arguments MAXTIME auf eine gewisse Zeit zu beschränken. Dabei wird sich der letzte optimierte Zeitpunkt gemerkt und beim nächsten Anlauf dort weiter fortgeführt. Um eine genauere Vorstellung von der Funktionsweise zu erhalten, werden wir im Folgenden einige Optimierungen durchführen. Folgende Indexfragmentierung sei beim Index vorhanden, ausgelöst durch INSERT und DELETE Operationen. Die Ausgabe erfolgt analog zum Blog.


---------------------------------------------------------------------------
FRAGMENTATION STATISTICS
---------------------------------------------------------------------------

total size of $I data:                                270,000 (263.67 KB)

$I rows:                                                           90,000
estimated $I rows if optimal:                                          72
estimated row fragmentation:                                        100 %

garbage docids:                                                     7,001
estimated garbage size:                                 52,297 (51.07 KB)

most fragmented tokens:
  SAT (0:TEXT)                                                      100 %
  MAT (0:TEXT)                                                      100 %
  MARY (0:TEXT)                                                     100 %
  LAMB (0:TEXT)                                                     100 %
  CAT (0:TEXT)                                                      100 %
  LITTLE (0:TEXT)                                                   100 %

Offensichtlich ist der Index fragmentiert und besitzt Garbage (gelöschte Daten). Wir werden nun den Index mit folgendem Kommando optimieren und dabei den Modus FAST verwenden:

execute ctx_ddl.optimize_index (idx_name => 'TESTX', optlevel => 'FAST', parallel_degree => 1);

Nach Abschluss der OPTIMIZE-Operation monitoren wir wieder die Fragmentieren. Die Fragmentierung ist verschwunden, allerdings ist noch Garbage vorhanden.

---------------------------------------------------------------------------
FRAGMENTATION STATISTICS
---------------------------------------------------------------------------

total size of $I data:                                270,003 (263.67 KB)

$I rows:                                                               72
estimated $I rows if optimal:                                          72
estimated row fragmentation:                                          0 %

garbage docids:                                                     7,001
estimated garbage size:                                 52,298 (51.07 KB)

most fragmented tokens:
  SAT (0:TEXT)                                                        0 %
  MAT (0:TEXT)                                                        0 %
  MARY (0:TEXT)                                                       0 %
  LAMB (0:TEXT)                                                       0 %
  CAT (0:TEXT)                                                        0 %
  LITTLE (0:TEXT)                                                     0 %


Nun führen wir das Ganze statt im FAST Modus im FULL Modus aus:

execute ctx_ddl.optimize_index (idx_name => 'TESTX', optlevel => 'FULL', parallel_degree => 1);

Parallel können wir in einer zusätzlichen Session, die Optimierung beobachten:

SQL>set pagesize 100
SQL>col indx_name format a30
SQL>col idx_opt_type format a20

SQL> SELECT idx_name,idx_opt_token,idx_opt_type,idx_opt_count FROM ctxsys.dr$index; 
IDX_NAME                              IDX_OPT_TOKEN IDX_OPT_TYPE IDX_OPT_COUNT
-------------------- ------------------------------ ------------ -------------
D01_F_ALL
SUP_TEXT_IDX
AUTH_IDX
IDX_TEXT
TESTX MAT                                                      0          7001
TEXT_IND

Mit unserem Monitoring Skript erhalten wir nun folgende Information über die Fragmentierung:

---------------------------------------------------------------------------
FRAGMENTATION STATISTICS
---------------------------------------------------------------------------

total size of $I data:                                206,997 (202.15 KB)
$I rows:                                                               57
estimated $I rows if optimal:                                          57
estimated row fragmentation:                                          0 %

garbage docids:                                                         0
estimated garbage size:                                                 0

most fragmented tokens:
  SAT (0:TEXT)                                                        0 %
  MAT (0:TEXT)                                                        0 %
  MARY (0:TEXT)                                                       0 %
  LAMB (0:TEXT)                                                       0 %
  CAT (0:TEXT)                                                        0 %
  LITTLE (0:TEXT)                                                     0 %



Stellt man fest, dass häufig nach einzelnen Tokens gesucht wird, könnte man die Optimierung auch auf einzelne Tokens oder Token-Types (im Fall der MDATA Nutzung) beschränken. Im folgenden Beispiel werden wir dies für das Token LITTLE durchführen: Das Ergebnis sieht dann folgendermassen aus:

---------------------------------------------------------------------------
                         FRAGMENTATION STATISTICS
---------------------------------------------------------------------------

total size of $I data:                                263,998 (257.81 KB)

$I rows:                                                           80,007
estimated $I rows if optimal:                                          71
estimated row fragmentation:                                        100 %

garbage docids:                                                     7,001
estimated garbage size:                                 51,134 (49.94 KB)

most fragmented tokens:
  SAT (0:TEXT)                                                      100 %
  MAT (0:TEXT)                                                      100 %
  MARY (0:TEXT)                                                     100 %
  LAMB (0:TEXT)                                                     100 %
  CAT (0:TEXT)                                                      100 %
  LITTLE (0:TEXT)                                                     0 %

Mehr zur Optimierung in einem der nächsten Blogs....

Beliebte Postings