Gibt es einen Leistungsgewinn bei der Indizierung eines booleschen Feldes?


101

Ich bin gerade dabei, eine Abfrage zu schreiben, die a enthält WHERE isok=1. Wie der Name schon sagt, isokhandelt es sich um ein boolesches Feld (tatsächlich ein Feld TINYINT(1) UNSIGNED, das je nach Bedarf auf 0 oder 1 gesetzt wird).

Gibt es einen Leistungsgewinn bei der Indizierung dieses Feldes? Würde die Engine (in diesem Fall InnoDB) beim Nachschlagen des Index besser oder schlechter abschneiden?


Antworten:


78

Nicht wirklich. Sie sollten wie ein Buch darüber nachdenken. Wenn ein Buch nur drei Arten von Wörtern enthält und Sie alle indizieren, haben Sie die gleiche Anzahl von Indexseiten wie normale Seiten.

Es würde einen Leistungsgewinn geben, wenn es relativ wenige Datensätze mit einem Wert gibt. Wenn Sie beispielsweise 1000 Datensätze haben und 10 davon WAHR sind, ist es hilfreich, wenn Sie mit suchenisok = 1

Wie Michael Durrant erwähnte, verlangsamt es auch das Schreiben.

EDIT: Mögliche Duplizierung: Indizierung von Booleschen Feldern

Hier wird erklärt, dass selbst wenn Sie einen Index haben, wenn Sie zu viele Datensätze haben, der Index sowieso nicht verwendet wird. MySQL verwendet keinen Index, wenn = 1 überprüft wird, sondern verwendet ihn mit = 0


4
Sieht aus wie es "ja: 2 - nein: 1". Hier liegt jemand falsch, aber wer?
Niet the Dark Absol

4
Dies ist nicht ganz richtig, ohne einen Index muss mySql die gesamte Tabelle scannen, um die relevanten Zeilen zu finden.
Ilanco

4
Andernfalls würde der gesamte Index gescannt. (was in den meisten Fällen genauso lang ist)
Michael Koper

1
Es kann einen Unterschied machen. Reduzieren Sie einfach die Ausführungszeit um die Hälfte einer Abfrage, indem Sie einfach einen Index hinzufügen. Schreibvorgänge sind selten und billig genug, sodass uns die Strafe nicht wirklich wichtig ist. Wie bei allem, nehmen Sie nicht an, messen Sie (auch weil sich Datenbanken nicht immer so verhalten, wie Sie es logischerweise erwarten würden)
Eelco

6
Dies setzt eine gleichmäßige Verteilung zwischen TRUE und FALSE voraus. Wie von @oucil unten erwähnt, kann es noch eine Weile dauern, bis Sie nach einem booleschen Wert suchen, der ziemlich selten ist. Das heißt nicht, dass Sie immer indizieren sollten, aber ich würde annehmen, dass die Art Ihrer Daten und Ihre Abfragen auch bei den meisten Datenbank-Engines von Bedeutung sind.
Mahemoff

117

Um einige andere Antworten hier genauer zu formulieren: Da sich meiner Erfahrung nach diejenigen, die Fragen wie diese betrachten, im selben Boot befinden wie wir, haben wir alle gehört, dass das Indizieren von Booleschen Feldern sinnlos ist, und doch ...

Wir haben eine Tabelle mit ungefähr 4 Millionen Zeilen, von denen jeweils nur ungefähr 1000 einen Booleschen Schalter markiert haben, und danach suchen wir. Das Hinzufügen eines Index für unser Boolesches Feld beschleunigte die Abfragen um Größenordnungen und ging von mehr als 9 Sekunden auf einen Bruchteil einer Sekunde.


Ja, während Sie definitiv versuchen sollten, das "Warum" der Dinge zu verstehen, messen Sie immer nebeneinander und probieren Sie verschiedene Dinge in Ihrem tatsächlichen Datensatz aus, um festzustellen, ob Ihre Theorie mit dem tatsächlichen Verhalten der DB-Engine übereinstimmt (Sie wären überrascht ... )
Eelco

8
@Eelco Sie haben Recht, aber in diesem Fall stimmt das Ergebnis tatsächlich gut mit der Grundtheorie überein. Die Grundidee, dass es vernachlässigbar sein sollte, ist nur dann sinnvoll, wenn Sie mit einer Wahrscheinlichkeit von etwa 50% auf Elemente stoßen, die Ihrer Suche entsprechen. Um 100 Übereinstimmungen zu finden, muss die Datenbank 200 Elemente iterieren. Wenn die Elemente jedoch nur in 1% der Fälle übereinstimmen, müssen 10.000 Elemente wiederholt werden.
Mahemoff

6
Ich mag es, wenn Leute Dinge auf dem Feld ausprobieren und Feedback zum Leistungsgewinn geben, anstatt nur zu philosophieren.
Viktor Joras

WHERE my_col > 0 statt my_col = 1scheint auch zu beschleunigen
Aaron

27

Dies hängt von den tatsächlichen Abfragen und der Selektivität der Index / Abfrage-Kombination ab.

Fall A : Zustand WHERE isok = 1und sonst nichts da:

SELECT *
FROM tableX
WHERE isok = 1
  • Wenn der Index selektiv genug ist (sagen wir, Sie haben 1 Million Zeilen und nur 1 KB isok = 1), wird die SQL-Engine den Index wahrscheinlich verwenden und schneller sein als ohne.

  • Wenn der Index nicht selektiv genug ist (z. B. 1 Million Zeilen und mehr als 100.000 isok = 1), verwendet die SQL-Engine den Index wahrscheinlich nicht und führt einen Tabellenscan durch.

Fall B : Zustand WHERE isok = 1und mehr Zeug:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Dann hängt es davon ab, welche anderen Indizes Sie haben. Ein Index für another_columnwäre wahrscheinlich selektiver als der Index, für isokden nur zwei mögliche Werte vorliegen. Ein Index auf (another_column, isok)oder (isok, another_column)wäre noch besser.


Ich denke, dies ist die korrektere Antwort im Vergleich zur obersten. auch die Verteilung der Daten.
Tyan

11

Dies hängt von der Verteilung der Daten ab.

Stellen Sie sich vor, ich hätte ein Buch mit 1000 eng getippten Seiten, und die einzigen Wörter in meinem Buch waren "Ja" und "Nein", die immer wieder wiederholt und zufällig verteilt wurden. Wenn ich gebeten würde, alle Instanzen von "Ja" zu kreisen, würde ein Index am Ende des Buches helfen? Es hängt davon ab, ob.

Wenn es eine halb und halb zufällige Verteilung von Ja und Nein gäbe, würde es nicht helfen, im Index nachzuschlagen. Der Index würde das Buch viel größer machen, und trotzdem würde ich schneller von vorne beginnen und mich durch jede Seite arbeiten, um nach allen Instanzen von "Ja" zu suchen und sie zu umkreisen, anstatt jedes Element darin nachzuschlagen den Index und dann den Verweis vom Indexeintrag auf die Seite, auf die er verweist.

Aber wenn es in meinem tausendseitigen Buch nur zehn Fälle von "Ja" gäbe und alles andere nur Millionen von "Nein", würde mir ein Index viel Zeit sparen, wenn ich diese zehn Fälle von "Ja" finde und sie umkreise .

In Datenbanken ist es genauso. Wenn es sich um eine 50: 50-Verteilung handelt, hilft ein Index nicht weiter - das Datenbankmodul ist besser dran, wenn Sie nur die Daten von Anfang bis Ende durchforsten (vollständiger Tabellenscan), und der Index würde die Datenbank nur vergrößern, und langsamer zu schreiben und zu aktualisieren. Wenn es sich jedoch um eine 4000: 1-Verteilung handelt (wie in diesem Thread beschrieben), kann eine Indexsuche die Verteilung erheblich beschleunigen, wenn es sich um die 1: 4000-Elemente handelt, nach denen Sie suchen.


5

Nein, normalerweise nicht.

Normalerweise indizieren Sie Felder für die Suche, wenn sie eine hohe Selektivität / Kardinalität aufweisen. Die Kardinalität eines Booleschen Feldes ist in den meisten Tabellen sehr gering. Es würde auch Ihre Schreibvorgänge etwas langsamer machen.


3

Tatsächlich hängt dies von den von Ihnen ausgeführten Abfragen ab. Aber im Allgemeinen ja, sowie das Indizieren eines Feldes eines anderen Typs.


2

Ja, ein Index verbessert die Leistung. Überprüfen Sie die Ausgabe von EXPLAIN mit und ohne Index.

Aus den Dokumenten:

Indizes werden verwendet, um Zeilen mit bestimmten Spaltenwerten schnell zu finden. Ohne Index muss MySQL mit der ersten Zeile beginnen und dann die gesamte Tabelle durchlesen, um die relevanten Zeilen zu finden. Je größer der Tisch, desto mehr kostet dies. Wenn die Tabelle einen Index für die betreffenden Spalten enthält, kann MySQL schnell die Position bestimmen, nach der in der Mitte der Datendatei gesucht werden soll, ohne alle Daten anzeigen zu müssen.

Ich denke, es ist auch sicher zu sagen, dass ein Index in diesem Fall die Performance nicht VERRINGERT , sodass Sie nur davon profitieren müssen.


2
Ein Index enthält viele Daten auf der Festplatte und verlangsamt das Schreiben, sodass Sie nicht nur davon profitieren.
Michael Koper

1
Richtig, aber in diesem Fall einer TINYINT(1) UNSIGNEDSpalte ist die Größe der Daten klein.
Ilanco

Und der zusätzliche Schreibaufwand ist wahrscheinlich ziemlich gering
Eelco

Wird die Größe des Index nicht mit der Anzahl der Zeilen, auf die er zeigt, zunehmen, nicht nur mit der Größe des indizierten Felds?
Poolie
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.