2016-12-21 5 views
2

Ich habe eine Tabelle mit den Spalten 'A' und 'B'.Index für spärliche Spalte definieren

'A' ist eine Spalte mit 90% 'Null' und 10% verschiedenen Werten, und die meiste Zeit suche ich nach einem Datensatz mit einem oder zwei dieser verschiedenen Werte.

und 'B' ist eine Spalte mit 90% Wert = '1' und 10% verschiedenen Werten und die meiste Zeit ich abfragen, um mit einem oder zwei dieser verschiedenen Werte zu haben.

In dieser Tabelle haben wir die meiste Zeit DML-Transaktion.

jetzt, ich weiß nicht definieren Index auf diese Spalten ist gut? wenn ja welche Art von Index?

+0

Werden diese DML-Sitzungen von mehreren Sitzungen oder nur einer einzigen Sitzung ausgeführt? –

+1

Oracle indiziert keine Werte, bei denen alle Spalten null sind. Ein Index für "x (a)" enthält also nur die Nicht-Null-Werte. –

+0

@WernfriedDomscheit erledigt durch mehrere Sitzungen –

Antwort

0

Zum Beispiel, wenn Sie Index a_b_idx auf A, B (in dieser Reihenfolge):

  • a) ... auswählen ... A = ... Index verwenden

  • b) ... auswählen ... mit B = ... Index nicht

Auf der anderen Seite verwenden, wenn Sie index b_a_idx auf B, A:

  • a) wählen ... von ... wobei A = ... nicht Index

  • b verwenden) wählen ... aus. .. wo B = ... wird Index

Oracle verwenden, nicht zweite Spalte in Index verwenden kann, wenn er nicht auf dem ersten Spalte nicht filtern, da in regelmäßigen Fällen Index baumartige Struktur ist: column1 -> Spalte2-> Spalte3-> etc.

Sie benötigen Index nur für Spalte A oder für Spalte A, B, wenn Sie Abfragen wie a) durchführen.

Sie benötigen einen Index nur für Spalte B oder für Spalten B, A, wenn Sie Abfragen wie b) ausführen.

Oracle speichert keine NULL-Werte im Index, aber es kann NULL-Wert für A speichern, wenn B einen NULL-Wert enthält.

Manchmal ist es fruchtbarer, ganze Tabelle in den Speicher zu lesen und den Index zu ignorieren. Der Optimierer kann dies tun, wenn die Ergebnismenge groß ist und für alle Datensätze gilt, da der Übergang von Index zu Datensatz mehr kostet als das Lesen einfacher Datensätze.

Auch manchmal passiert es fälschlicherweise für Tabellen ohne Statistiken, so dass Sie entweder Jobs mit alter table ... compute Statistiken oder Oracle 11+, die Statistiken wie diese ohne Jobs berechnen können.

Meistens ist ein anderer Index eine gute Sache für Abfragen, aber schlechte Sache für Updates/Datenträger. Jeder Index belegt Speicherplatz und jede Aktualisierung von Datensätzen führt Aktualisierungen für jeden Index durch. Daher ist es für stark aktualisierte Tabellen nicht gut, viele Indizes zu haben, aber für häufig abgefragte Tabellen ist es besser, Indizes für alle gängigen Fälle zu haben.

Für die meisten flachen Abfragen (ohne Joins/Unterabfragen/Hierarchien) wird nur 1 Index verwendet, so dass Indizes für jede Spalte im Allgemeinen nur eine Verschwendung von Speicherplatz ist. Sie benötigen einen mehrspaltigen Index zur Optimierung von A = ... und B = ...

Wie beim Indextyp benötigen Sie wahrscheinlich einfache, nicht eindeutige Indizes.

+1

vielen Dank. aber bezieht sich deine Antwort auf meine Frage ?! –

+2

@AlexanderAnikin - Oracle hat seit einiger Zeit INDEX SKIP SCAN, daher ist der erste Teil der Antwort nicht mehr der Fall. Werfen Sie einen Blick auf http://docs.oracle.com/cd/B19306_01/server.102/b14211/optimops.htm#i51571 – BriteSponge

1

Im Prinzip wäre der Bitmap-Index in dieser Situation am besten. Aufgrund der Mehrbenutzerumgebung sind sie jedoch nicht geeignet - Sie würden Ihre Anwendung durch Tabellensperren erheblich verlangsamen und vielleicht sogar Deadlocks erhalten.

Vielleicht können Sie Ihre Anwendung durch intelligente Aufteilung und Nutzung von Partial Indexes (neue Funktion in Oracle 12c)

CREATE unter TABLE-Anweisungen optimieren sollten gleichwertig sein.

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS) 
PARTITION BY LIST (a) SUBPARTITION BY LIST (b) (
    PARTITION part_a_NULL VALUES (NULL) (
     SUBPARTITION part_a_NULL_b_1 VALUES (1) INDEXING OFF, 
     SUBPARTITION part_a_NULL_b_other VALUES (DEFAULT) INDEXING ON 
    ), 
    PARTITION part_a_others VALUES (DEFAULT) (
     SUBPARTITION part_a_others_b_1 VALUES (1) INDEXING OFF, 
     SUBPARTITION part_a_others_b_other VALUES (DEFAULT) INDEXING ON 
    ) 
); 

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS) 
PARTITION BY LIST (a) SUBPARTITION BY LIST (b) 
    SUBPARTITION TEMPLATE (
     SUBPARTITION b_1 VALUES (1) INDEXING OFF, 
     SUBPARTITION b_other VALUES (DEFAULT) INDEXING ON 
    ) 
(
    PARTITION part_a_NULL VALUES (NULL), 
    PARTITION part_a_others VALUES (DEFAULT) 
); 

CREATE INDEX IND_A ON YOUR_TABLE (A) LOCAL INDEXING PARTIAL; 
CREATE INDEX IND_B ON YOUR_TABLE (B) LOCAL INDEXING PARTIAL; 

Dadurch verbraucht Ihr Index nur 10% des gesamten Tablespace. Wenn Ihre WHERE-Bedingung WHERE A IS NULL oder WHERE B = 1 ist, würde Oracle Optimizer solche Indizes sowieso überspringen.

mit dieser Abfrage Überprüfen

SELECT table_name, partition_name, subpartition_name, indexing 
FROM USER_TAB_SUBPARTITIONS 
WHERE table_name = 'YOUR_TABLE'; 

wenn INDEXING auf Wunsch Subpartitionen verwendet wird.

aktualisieren

Ich sehe gerade, tatsächlich ist dies ein viel des Guten, weil NULL-Werte in Spalte A erstellen keinen Index ohnehin Eintrag. So kann es zu vereinfachen

CREATE TABLE YOUR_TABLE (a INTEGER, b INTEGER, ... more COLUMNS) 
PARTITION BY LIST (b) (
    PARTITION part_b_1 VALUES (1) INDEXING OFF, 
    PARTITION part_b_other VALUES (DEFAULT) INDEXING ON 
); 
+0

Vielen Dank. Was ist der Unterschied zwischen Ihrer Lösung und Filtered Index (simulieren nach Funktionsindex)? –

+0

Diese Lösung erstellt Indexeinträge nur dort, wo es sinnvoll ist (d. H. Mit geringer Kardinalität bzw. vielen verschiedenen Werten) und hält sie klein und effizient. Mit einem funktionsbasierten Index wie 'nvl (A, 'XX')' erzwingst du die Erstellung eines Indexeintrags für jeden Datensatz - egal ob dies sinnvoll ist oder nicht. –

+0

in bedeutet, dass für Spalte A, wenn ich Index erstellen, obwohl Orakel nicht Index für Null verwendet, die Kosten für die Verwendung von Index ist das gleiche wie alle Datensatz hat Wert? –

0
  • Spalte A

Nehmen wir an, dass Sie einen Index erstellen namens _columnA_index_. Im Allgemeinen enthalten Indizes in RDBMS keine NULL-Werte. Dies bedeutet, dass in _columnA_index_ keine Indexeinträge vorhanden sind, die auf Datensätze mit NULL-Werten verweisen. Somit wird die folgende Abfrage

Q1: select * from MyTable where A is null; 

wird in einer Tabelle führen, anstatt scannen (oder DBMS wählt einen anderen Index auf einer anderen Spalte zu verwenden, falls vorhanden)

Da es jedoch 10% der Datensätze ‚verschiedene Werte aufweisen ', die _columnA_index_ hilft natürlich zB bei Abfragen.

Q2: select * from MyTable where A = '123'; 

Im obigen Beispiel, wenn die Abfrage < 1% der Datensätze zurückgibt, ist die _columnA_index_ hilfreich. Je nachdem, wie selektiv die Abfrage ist, verbessert der Index die Leistung erheblich. Sie können einen Index erstellen, der für den Datentyp der Spalte A geeignet ist.

  • Spalte B

In ähnlicher Weise ein Index für B nicht

Q3: select * from MyTable where B = 1; 

aber es wird helfen, mit unterschiedlichen Werten

Q4: select * from MyTable where B = '456'; 
  • NULL-Werte
  • helfen

Bis jetzt antwortete ich, dass jeder Index nicht mit NULL-Werten hilft. Wenn Sie also Q1 die meiste Zeit abfragen müssen, schlage ich folgende Ideen

  • Stellen Sie sicher, dass Ihre Version von DBMS NULL-Werte in Indizes aufgenommen werden unterstützt. Zum Beispiel Oracle 11g aber nicht Versionen davor.

  • Planen Sie den funktionsbasierten Index here erneut mit Oracle. Aber Sie können die Idee zumindest nehmen.

  • Redesign der Logik Ihrer Anwendung/Ihre Notwendigkeit, Abfragen auf Null-Werte. Ich bevorzuge diesen Ansatz.

+0

Funktionsbasierter Index wie 'create index ... on ... (nvl (A, 'XX'));' wäre nutzlos (d. H. Platzverschwendung), weil der Oracle Optimizer diesen Index sowieso überspringt. –

+0

@WernfriedDomscheit, du bist ganz richtig aber nicht ganz richtig. Sie können das Optimierungsprogramm erzwingen, den funktionsbasierten Index in den Abfrageplan aufzunehmen, oder den funktionsbasierten Index in der Abfrage verwenden. – tcthanh

+0

In diesem Fall ist der Index tatsächlich sehr hilfreich. – tcthanh

Verwandte Themen