2010-01-21 12 views
29

Ich bin hauptsächlich ein Actionscript-Entwickler und keineswegs ein Experte für SQL, aber von Zeit zu Zeit muss ich einfach Server-seitiges Zeug entwickeln. Also, ich dachte, ich würde erfahrenere Leute über die Frage im Titel fragen.Macht es Sinn, einen Index zu verwenden, der eine geringe Kardinalität hat?

Mein Verständnis ist, dass Sie nicht viel gewinnen, indem Sie einen Index in einer Spalte setzen, die einige unterschiedliche Werte enthalten wird. Ich habe eine Spalte, die einen booleschen Wert enthält (eigentlich ist es ein kleines int, aber ich benutze es als Flag), und diese Spalte wird in den WHERE-Klauseln der meisten Abfragen verwendet, die ich habe. In einem theoretischen "durchschnittlichen" Fall wird die Hälfte der Datensätze 1 und die andere Hälfte 0 sein. In diesem Szenario könnte die Datenbank-Engine einen vollständigen Tabellenscan vermeiden, muss aber trotzdem viele Zeilen lesen (Gesamtreihen/2).

Also, sollte ich diese Spalte zu einem Index machen?

Für die Aufzeichnung verwende ich Mysql 5, aber ich interessiere mich mehr für eine allgemeine Begründung, warum es Sinn macht, eine Spalte zu indizieren, die ich kenne, die eine niedrige Kardinalität haben wird.

Vielen Dank im Voraus.

Antwort

2

Normalerweise mache ich einen einfachen "haben Index" vs "habe nicht" Index-Test. Meiner Erfahrung nach erhalten Sie den größten Teil der Leistung für Abfragen, die ORDER BY in der indizierten Spalte verwenden. Falls Sie in dieser Spalte sortieren, wird die Indexierung wahrscheinlich helfen.

+0

Danke für Ihre Antwort. In diesem Fall sortiere ich jedoch nicht in dieser Spalte. Es dient nur dazu, einen Eintrag als aktiviert/deaktiviert zu kennzeichnen. Ich benutze es im Grunde für die weiche Löschung. Deshalb muss ich es in der WHERE-Klausel der meisten Abfragen verwenden. –

2

IMHO ist es von begrenzter Nützlichkeit. Ich nehme an, in den meisten Fällen gibt es andere Kriterien, die Sie in Ihren Abfragen neben der Flagge verwenden, die wahrscheinlich viel mehr helfen.

Bei 50% würde ich wahrscheinlich ein Benchmarking mit/ohne durchführen und sehen, ob es viel Unterschied macht.

8

Es könnte sich lohnen, das boolesche Feld in einen zusammengesetzten Index aufzunehmen. Zum Beispiel, wenn Sie eine große Tabelle mit Nachrichten, die in der Regel nach Datum geordnet werden müssen, aber Sie haben auch einen Booleschen Feld gelöscht, so oft Sie es wie folgt abfragen:

SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end 

Sie werden auf jeden Fall profitieren von mit ein zusammengesetzter Index für die Deleted und Date Felder.

+0

Danke. Vielleicht sollte ich etwas über zusammengesetzte Indizes recherchieren (ich kenne nur die existieren, aber habe sie nicht wirklich wirklich benutzt). Ich benutze diese Spalte in sehr ähnlicher Weise zu Ihrem Beispiel-Code (obwohl es Joins und andere Sachen gibt, aber die WHERE-Klausel immer diese Markierung zum Markieren der weichen Löschung haben). –

56

Ein Index kann auch auf Low Mächtigkeit Felder helfen, wenn:

  1. Wenn einer der möglichen Werte sehr selten ist im Vergleich zu den anderen Werten und Sie danach suchen.

    Zum Beispiel gibt es nur sehr wenige farbenblind Frauen, so dass diese Abfrage:

    SELECT * 
    FROM color_blind_people 
    WHERE gender = 'F' 
    

    würde höchstwahrscheinlich aus einem Index auf gender profitieren.

  2. Wenn neigen die Werte in der Tabelle gruppiert werden:

    SELECT * 
    FROM records_from_2008 
    WHERE year = 2010 
    LIMIT 1 
    

    Obwohl es hier nur 3 deutliche Jahre sind, Aufzeichnungen mit früheren Jahren sind die meisten wahrscheinlich zuerst so sehr viele Datensätze müssten hinzugefügt werden gescannt, bevor der erste 2010 Datensatz zurückgegeben wird, wenn nicht für den Index.

  3. Wenn Sie ORDER BY/LIMIT benötigen:

    SELECT * 
    FROM people 
    ORDER BY 
         gender, id 
    LIMIT 1 
    

    Ohne den Index wäre ein filesort erforderlich. Obwohl es etwas optimiert ist, um die LIMIT zu tun, würde es immer noch eine vollständige Tabelle Scan benötigen.

  4. Wenn der Index alle Felder in der Abfrage verwendet umfasst:

    CREATE INDEX (low_cardinality_record, value) 
    
    SELECT SUM(value) 
    FROM mytable 
    WHERE low_cardinality_record = 3 
    
  5. Wenn Sie benötigen DISTINCT: wird verwenden INDEX FOR GROUP-BY

    SELECT DISTINCT color 
    FROM tshirts 
    

    MySQL, und wenn Sie einige Farben haben, um diese Abfrage wird sofort sogar mit Millionen von Aufzeichnungen sein.

    Dies ist ein Beispiel für ein Szenario, wenn der Index für ein Feld mit niedriger Kardinalität mehr effizienter als das auf einem hohen Kardinalitätsfeld ist.

Beachten Sie, dass, wenn DML Leistung nicht viel zu einem Thema ist, dann sicher es ist, den Index zu erstellen.

Wenn der Optimizer denkt, dass der Index ineffizient ist, wird der Index nicht verwendet.

Verwandte Themen