2017-02-22 23 views
2

Ich habe große Tabelle ir_data (150GB), die Daten für verschiedene Daten enthält (Spalte val_date). Ich muss wissen, ob ein bestimmtes Datum in der ir_data an verschiedenen Stellen in meiner Anwendung verfügbar ist.Puzzling Leistung der Index-Scan. Warum ist der Scan-Index langsam, obwohl Ergebnismenge ist klein und indiziert

select distinct(val_date) from ir_data 

I das folgende Experiment ir_data enthält 29 verschiedene Werte für val_date.


SETUP 1

erwartete ich einen Index für ir_data (val_date, key_id, other_colum) schnell die 29 Werte der Suche zu helfen. In der Tat nimmt diese mehr als 5 Minuten:

Abfrage 1 von 1, Zeilen lesen: 29, Abgelaufene Zeit (Sekunden) - Gesamt: 343,96, SQL-Abfrage: 343,958, Leseergebnisse: 0,002

Ich habe immer erwartet, dass ein Index ein Baum ist, in dem die Knoten in einer Baumstruktur gespeichert sind, z wie dieser

val_date -> key_id -> other_column -> data-nodes 

1.1.2017 -> 0-50  -> A   -> (1.1.2017, 0, Automobile), (1.1.2017, 2, Amsterdam) 
        -> B-E   -> (1.1.2017, 12, Batman) 
     -> 51-100 -> A   -> ... 
         X 
     -> 666-1000 -> A 
        -> B-C 
        -> E 
2.1.2017 -> ... 

Basierend auf dieser Struktur sollten die 29 verschiedenen val_dates sehr schnell sein.

Frage: Warum dauert das so lange ???

Unterfrage: Gibt es eine Möglichkeit, dies zu beheben, ohne eine andere Tabelle zu erstellen?


SETUP 2

habe ich einen weiteren Index, der nur val_date enthält. Es dauert ungefähr die gleiche Zeit.


Abfrage-Plan:

The type of query is SELECT. 

2 operator(s) under root 

    |ROOT:EMIT Operator (VA = 2) 
    | 
    | |GROUP SORTED Operator (VA = 1) 
    | |Distinct 
    | | 
    | | |SCAN Operator (VA = 0) 
    | | | FROM TABLE 
    | | | ir_data 
    | | | Index : ir_data_idx1 <-- this is the index containing only val_date. 
    | | | Forward Scan. 
    | | | Positioning at index start. 
    | | | Index contains all needed columns. Base table will not be read. 
    | | | Using I/O Size 16 Kbytes for index leaf pages. 
    | | | With MRU Buffer Replacement Strategy for index leaf pages. 
+1

Was ist Ihre Abfrage? –

+0

@OfirWinegarten ja, das hätte ich erwähnen sollen. Hinzugefügt. – Beginner

Antwort

2

Ihr Tisch ist sehr groß und Ihr Index. Wie Sie im Plan sehen können, führt die Engine einen Index-Scan durch. Dieser Vorgang wird langwierig sein, da er Ihren ganzen Index nach verschiedenen Werten scannt.

Als ersten Schritt könnten Sie update index statistics auf den Index versuchen, obwohl ich nicht wirklich denke, dass es helfen wird.

Wenn es eine einmalige manuelle Operation ist, denke ich, dass Sie mit dem 5 Minuten-Betrieb zufrieden sein werden.

Wenn es eine Abfrage von der Anwendung ausgeführt ist, dann haben Sie die Wahl zwischen 2 ich denken kann:

  1. Wie Sie in der Frage gesagt - die Tabelle normalisiert durch zusätzliche Tabelle für die Tage, die Erstellung und FK verwenden.
  2. Erstellen Sie eine precomputed result set. Dies ist eine materialisierte Ansicht - die Ergebnisse werden wie eine normale Tabelle gespeichert (im Gegensatz zu einer Ansicht, in der nur ihre Definition gespeichert ist).
    Es aktualisiert automatisch die Ergebnisse in der Ansicht und Werte werden schnell abgerufen.
    Wichtig: wie Indizes, wird es Auswirkungen auf die Leistung von Insert, Update haben ...
    kann es wirken:

    create precomputed result set prs_ir_data 
    immediate refresh 
    as 
    select distinct val_date 
    from ir_data 
    

Sie here und here über vorberechneten Ergebnis ablesen Set

+0

Danke. Weißt du, welche Art von Datenstruktur sie verwenden? Ich finde es schwierig zu verstehen, warum es notwendig sein sollte, den gesamten Index zu scannen, nur um das oberste Attribut der Suchstruktur zu finden. – Beginner

+0

Die Fremdschlüsselidee ist sehr gut, daran habe ich nicht gedacht. – Beginner

+0

Ich bin froh, dass ich helfen konnte. Ich bin mir nicht sicher über die interne Struktur von Sybase-Indizes, aber sicherlich ist es eine Art von B-Baum für schnelle Suchen und Einfügungen –

0

Ein recursive CTE beschleunigt diese Abfrage erheblich, dh sehr wenige unterschiedliche Werte in einer großen Tabelle. Das Problem besteht darin, dass die Indexsuche während der Suche nach bestimmten Werten derzeit nicht implementiert ist. Hier ist eine link to the approach.