News zu Oracle

DBA Tipp: Früh­jahrs­putz im Index-Tablespace

Bei unserem internen “Früh­jahrs­putz” sind wir auf einen Beitrag von Oracle Certified Master Thilo aus dem Jahr 2020 zu genau diesem Thema gestoßen. Konkret geht es hier um den Früh­jahrs­putz im Index-Ta­b­le­space und warum es sich lohnt, diesen ab und zu mal auf­zu­räu­men. Die Grund­sät­ze und Queries treffen heute noch genauso zu wie damals, also Ärmel hoch­krem­peln und los geht’s!

Während Indizes grund­sätz­lich wichtig für eine per­for­man­te Aus­füh­rung von DML und Queries sind, haben sie gleich­zei­tig auch Nachteile, denn:

  • Jeder Index ver­ur­sacht durch den im­pli­zi­ten Pfle­ge­auf­wand Overhead bei DML-Operationen.
  • Jeder Index belegt wert­vol­len Platz in der Datenbank und im Backup.
  • Die Be­rech­nung von In­dex­sta­tis­ti­ken ver­braucht Zeit und ver­ur­sacht Last in der Datenbank.


Ziel sollte es daher sein, nicht mehr Indizes vor­zu­hal­ten, als für eine per­for­man­te Ab­wick­lung der typischen Workload er­for­der­lich sind.

Im Rahmen von Per­for­man­ce­un­ter­su­chun­gen und He­alth­checks unserer Kun­den­sys­te­me treffen wir häufig auf Indizes, die vom Grundsatz her nicht er­for­der­lich sind. Zwei häufige Fälle – und Queries zum Auffinden ent­spre­chen­der „Kan­di­da­ten“ – werden in diesem DBA Tipp vorgestellt.

Fall 1 – ver­tausch­te Spaltenreihenfolge

Abbildung 1

In Abbildung 1 siehst du die Indizes NDX_NAME_OWN_OBJECTS und NDX_OWN_NAME_OBJECTS, welche dieselben Spalten in un­ter­schied­li­cher Rei­hen­fol­ge in­di­zie­ren. Hin­ter­grund einer der­ar­ti­gen In­di­zie­rung ist wahr­schein­lich die falsche Annahme, damit sowohl für die Query

SELECT *
FROM scott_objects
WHERE object_name='EMP'
AND owner='SCOTT'

als auch für

SELECT *
FROM scott_objects
WHERE owner='SCOTT'
AND object_name='EMP'

jeweils auf einen Index zu­rück­grei­fen zu können. Tat­säch­lich reicht einer der beiden Indizes voll­kom­men aus. Der Optimizer tauscht bei Bedarf die beiden WHERE-Attribute aus, sodass er auch bei (ver­meint­lich) falscher At­tri­but­rei­hen­fol­ge vom Index Gebrauch machen kann (Abbildung 2).

Abbildung 2

Den hier be­schrie­be­nen Fall einer In­di­zie­rung desselben Satzes von Spalten in un­ter­schied­li­cher Rei­hen­fol­ge findest du über folgende Query heraus (hier ein­ge­schränkt auf das Schema SCOTT):

WITH column_list AS
  ( SELECT DISTINCT index_owner, index_name,
    listagg(column_name,', ') within GROUP (
  ORDER BY column_name) over (partition BY index_name) cols
  FROM dba_ind_columns
  )
SELECT DISTINCT fst.index_owner,
  fst.index_name,
  snd.index_owner,
  snd.index_name,
  snd_cols.cols
FROM dba_ind_columns fst,
  dba_ind_columns snd,
  column_list fst_cols,
  column_list snd_cols
WHERE fst.table_owner  =snd.table_owner
AND fst.table_name     =snd.table_name
AND fst.index_owner    =fst_cols.index_owner
AND fst.index_name     =fst_cols.index_name
AND snd.index_owner    =snd_cols.index_owner
AND snd.index_name     =snd_cols.index_name
AND fst_cols.cols      =snd_cols.cols
AND fst.index_owner    ='SCOTT'
AND fst.index_name!    =snd.index_name

Fall 2 – Index als links­bün­di­ges Spalten-Subset eines anderen Indexes

In der Regel sind auch Indizes unnötig, die ein links­bün­di­ges Subset eines anderen Indexes sind. 
Abbildung 3

In Abbildung 3 ist der Index NDX_OWN_NAME_OBJECTS ein links­bün­di­ges Subset von NDX_OWN_NAME_STAT_OBJECTS, da er komplett und in iden­ti­scher Rei­hen­fol­ge seiner Spalten Be­stand­teil des Indexes NDX_OWN_NAME_STAT_OBJECTS ist (beides muss erfüllt sein). Grund­sätz­lich würde der Index NDX_OWN_NAME_OBJECTS zwar für die Query

SELECT *
FROM scott_objects
WHERE owner='SCOTT'
AND object_name='EMP'

gegenüber NDX_OWN_NAME_STAT_OBJECTS bevorzugt werden (Abbildung 4), da der Le­se­auf­wand geringer ist (in NDX_OWN_NAME_STAT_OBJECTS müssten mehrere Leaf-Blocks gelesen werden).

Abbildung 4

Al­ler­dings könnte dieselbe Query ebenso NDX_OWN_NAME_STAT_OBJECTS nutzen, auch wenn nur ein Teil der Attribute dieses Indexes in der Query angegeben ist (Abbildung 5).

Abbildung 5

Achte aber bitte darauf, dass diese Regel nur für links­bün­di­ge Subsets gilt. Auf NDX_NAME_STAT_OBJECT z.B. kann nicht ohne Weiteres zugunsten NDX_OWN_NAME_STAT_OBJECTS ver­zich­tet werden. Letzterer stimmt mit ersterem nämlich erst ab der zweiten Spalte überein (Abbildung 6).

Abbildung 6

Das würde bei Abfragen ohne OWNER-Attribut in der WHERE-Klausel dazu führen, dass gar kein Index genutzt oder bes­ten­falls ein INDEX SKIP SCAN durch­ge­führt wird. Dieser ist jedoch erheblich „teurer“ und langsamer als der INDEX RANGE SCAN auf dem ur­sprüng­li­chen Index (siehe Abbildung 7 vs. Abbildung 8).

Abbildung 7
Abbildung 8

Al­ter­na­tiv kannst du auch auf den „breiteren“ Index NDX_OWN_NAME_STAT_OBJECTS zugunsten des „schma­le­ren“ NDX_OWN_NAME_OBJECTS ver­zich­ten, da der schmalere Index per se kleiner als der breitere ist. Hier solltest du al­ler­dings drei nicht un­we­sent­li­che Dinge im Hin­ter­kopf behalten:

  1. Du kannst nicht auf Indizes ver­zich­ten, die unique- oder primary key Cons­traints durchsetzen.

  2. Der Verzicht auf eine Spalte, die im ver­wor­fe­nen Index noch enthalten war, erhöht die CPU-Last, da nach dem In­dex­zu­griff jetzt noch ein Filtern in der Tabelle er­for­der­lich wird (Abbildung 9 vs. Abbildung 10).

  3. Queries, die bislang die an­ge­frag­ten Spalten schon im Index finden konnten, müssen nun neben dem Index auch noch auf die Tabelle zugreifen und werden folglich teurer und langsamer (Abbildung 11 vs. Abbildung 12).
Abbildung 9
Abbildung 10
Abbildung 11
Abbildung 12

Indizes, die links­bün­di­ge Subsets anderer Indizes und damit Lösch­kan­di­da­ten im Sinne dieses DBA Tipps sind, findest du mit folgender Query (ebenfalls ein­ge­schränkt auf das Schema SCOTT):

WITH column_list AS
  ( SELECT DISTINCT index_owner,
    index_name,
    listagg(column_name,', ') within GROUP (
  ORDER BY column_position) over (partition BY index_name) cols
  FROM dba_ind_columns
  )
SELECT DISTINCT fst.index_owner superset_owner,
  fst.index_name superset_index,
  fst_cols.cols superset_columns,
  snd.index_owner subset_owner,
  snd.index_name subset_index,
  snd_cols.cols subset_columns
FROM dba_ind_columns fst,
  dba_ind_columns snd,
  column_list fst_cols,
  column_list snd_cols
WHERE fst.table_owner=snd.table_owner
AND fst.table_name   =snd.table_name
AND fst.index_owner  =fst_cols.index_owner
AND fst.index_name   =fst_cols.index_name
AND snd.index_owner  =snd_cols.index_owner
AND snd.index_name   =snd_cols.index_name
AND fst_cols.cols LIKE snd_cols.cols||',_%'
AND fst.index_owner ='SCOTT'
AND fst.index_name! =snd.index_name

Wahr­schein­lich ist es dir bereits in diversen Screen­shots auf­ge­fal­len: Die bessere Al­ter­na­ti­ve zum Löschen der über­flüs­si­gen Indizes ist in diesem Fall das Ändern des In­dex­sta­tus auf „invisible“. Un­sicht­ba­re Indizes werden vom Optimizer nicht in Betracht gezogen, aber im Hin­ter­grund weiter aktuell gehalten. Sollte sich her­aus­stel­len, dass du mit einer Annahme „schwer daneben gelegen hast“ und einen Index wieder ak­ti­vie­ren musst, dann muss er in diesem Fall nur „visible“ gesetzt werden und ist sofort wieder verfügbar. Ein ge­lösch­ter (oder unusable gesetzter) Index hingegen müsste erst neu aufgebaut werden. Selbst­ver­ständ­lich sollten die invisible gesetzten Indexes nach an­ge­mes­se­ner Zeit letzt­end­lich dann doch gelöscht werden, denn nur so bekommst du den ganz oben erwähnten Overhead tat­säch­lich auch los.

Fazit

Indizes haben konträre Aus­wir­kun­gen auf eine Datenbank. Auf der einen Seite be­schleu­ni­gen sie DML und Queries, auf der anderen Seite erhöhen sie den Platz­be­darf und DML-Overhead. Daher sollten nicht mehr Indizes als absolut nötig in der Datenbank vorhanden sein. Mit Hilfe der oben erwähnten Queries lassen sich Indizes iden­ti­fi­zie­ren, die Duplikate oder Subsets anderer Indizes sind. Diese Duplikate können ten­den­zi­ell aus der Datenbank entfernt werden.

Übrigens: In­for­ma­tio­nen zum In­dex­mo­ni­to­ring findest du in unserem DBA-Tipp » Index-Mo­ni­to­ring – Aufspüren und Droppen von un­ge­nutz­ten Indizes in Da­ten­ban­ken. Index Mo­ni­to­ring hilft dir, Indizes auf­zu­spü­ren, die zwar exis­tie­ren, aber tat­säch­lich gar nicht benutzt werden.

Hier findest du weitere in­ter­es­san­te Posts zum Thema Oracle aus unserem News und Insights Bereich.

icon-arrow_right_medium-violet-blue.svg

Share this article

Facebook 
Twitter 
LinkedIn 
XING 
WhatsApp 
Email