Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Oracle 11 Index nur für einen Teil der Daten

Lassen Sie mich zunächst sicherstellen, dass ich die Frage richtig verstanden habe:

  • Sie möchten SELECT .. WHERE C_D IS NULL beschleunigen aber Sie nicht alle Abfragen beschleunigen möchten, die nach einem Nicht-NULL-C_D suchen.
  • Außerdem sollten Sie sicherstellen, dass sich keine "unnötigen" Nicht-NULL-Werte im Index befinden, um Platz zu sparen.

Wenn dieses Verständnis richtig ist, dann brauchen Sie eine funktionale Index. Ich bin. ein Index für eine Funktion in einem Feld, nicht ein Feld selbst...

CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS

...die Sie dann abfragen würden als...

SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...was äquivalent ist zu...

SELECT * FROM T WHERE C_D IS NULL

...aber schneller, da es den Index verwendet:

Dies spart Platz, da einspaltige Indizes keine NULL-Werte speichern. Verwenden Sie auch COMPRESS da der Index immer nur einen Schlüssel enthält, muss also kein Platz verschwendet werden, indem immer wieder derselbe Schlüssel in der Indexstruktur wiederholt wird.

HINWEIS:Unter Oracle 11 könnten Sie auch eine funktionsbasierte virtuelle Spalte (basierend auf dem CASE Ausdruck oben), dann indizieren und fragen Sie diese Spalte direkt ab, um wiederholte Eingaben zu sparen.

--- BEARBEITEN ---

Wenn Sie auch daran interessiert sind, C_I zusammen mit C_D IS NULL abzufragen , du könntest...

CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)

...und fragen Sie es ab mit (zum Beispiel)...

SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...was äquivalent ist zu...

SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL

...aber schneller, da es den Index T_IE2 verwendet .

Dies ist tatsächlich der einzige Index, den Sie für Ihre Tabelle benötigen (er "deckt" den Primärschlüssel ab, sodass Sie keinen separaten Index mehr nur für C_I benötigen). Das bedeutet auch, dass dieselbe ROWID nie in mehr als einem Index gespeichert wird, was Platz spart.

HINWEIS:COMPRESS für den Index T_IE2 nicht mehr sinnvoll .

--- BEARBEITEN 2 ---

Wenn Ihnen Einfachheit wichtiger ist als Platz, können Sie einfach einen zusammengesetzten Index für {C_I, C_D} erstellen. Oracle speichert NULL-Werte im zusammengesetzten Index, solange mindestens ein Nicht-NULL-Wert im selben Tupel vorhanden ist:

CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)

Dies verwendet den Index:

SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL

Wie im vorherigen EDIT ist dies der einzige Index, den Sie für Ihre Tabelle benötigen.