Indizierung von Booleschen Feldern


76

Dies ist wahrscheinlich eine wirklich dumme Frage, aber wird es von großem Vorteil sein, ein boolesches Feld in einer Datenbanktabelle zu indizieren?

In einer häufigen Situation, wie z. B. "Soft-Delete" -Datensätze, die als inaktiv gekennzeichnet sind und daher die meisten Abfragen enthalten WHERE deleted = 0, wäre es hilfreich, dieses Feld selbst zu indizieren, oder sollte es mit den anderen häufig gesuchten Feldern in a kombiniert werden anderer Index?



17
@AmirAliAkbari: Oh! Nein! Ein Zirkelverweis! Hoffentlich explodiert SO nicht!
Paul

Antworten:


59

Nein.

Sie indizieren Felder, die durchsucht werden und eine hohe Selektivität / Kardinalität aufweisen. Die Kardinalität eines Booleschen Feldes wird in fast jeder Tabelle ausgelöscht. Wenn überhaupt, werden Ihre Schreibvorgänge langsamer (um einen so winzigen Betrag).

Vielleicht würden Sie es zum ersten Feld im Clustered-Index machen, wenn jede Abfrage weiche Löschungen berücksichtigt?


5
Stellen Sie sich ein großes Buch mit Tausenden von Seiten vor. Seiten enthalten einen einzelnen Buchstaben, 'A' oder 'B' und eine Zufallszahl. Hätten Sie einen Vorteil darin, einen bestimmten Zufallszahleneintrag zu finden, für den Sie wissen, dass er sich auf einer der A-Seiten befindet, wenn A- und B-Seiten nicht gemischt sind, das Buch jedoch nur mit A-Seiten und dann mit B beginnt? Ja, du würdest ... also ich denke du
liegst

1
Bist du sicher, dass das richtig ist? Ich konnte leicht erkennen, dass ein solches Feld von Wert ist, wenn beispielsweise in 99% der Fälle der Wert "Nein" war und Sie nur die "Ja" -Werte abfragten. (EG nur aktive Aufzeichnungen?)
RonLugge

1
Ich denke, die Antwort ist angesichts vieler anderer Indizierungsstrategien in modernen Datenbanken zu einfach. Beispielsweise WHERE field = falsebieten ein Teilindex oder bestimmte andere Nicht-Btree-Indizes, die normalerweise plattformspezifisch sind, Alternativen zu einem Btree für die Suche nach Booleschen Werten. Dies hängt auch von Ihren Suchbedingungen ab und davon, welcher Teil der Tabelle wahr oder falsch ist.
DB140141

17

Was ist mit einer deleted_at DATETIME-Spalte? Es gibt zwei Vorteile.

  1. Wenn Sie einen eindeutigen spaltenähnlichen Namen benötigen, können Sie einen Datensatz mit demselben Namen mehrmals erstellen und sanft löschen (wenn Sie einen eindeutigen Index für die Spalten deleted_at AND name verwenden).
  2. Sie können nach kürzlich gelöschten Datensätzen suchen.

Ihre Abfrage könnte folgendermaßen aussehen:

SELECT * FROM xyz WHERE deleted_at IS NULL

6

Ich denke, es würde helfen, insbesondere bei der Abdeckung von Indizes.

Wie viel / wenig hängt natürlich von Ihren Daten und Abfragen ab.

Sie können Theorien aller Art über Indizes haben, aber die endgültigen Antworten werden von der Datenbank-Engine in einer Datenbank mit realen Daten gegeben. Und oft wundert dich die Antwort (oder vielleicht sind meine Theorien zu schlecht;)

Untersuchen Sie den Abfrageplan Ihrer Abfragen und stellen Sie fest, ob die Abfragen verbessert werden können oder ob die Indizes verbessert werden können. Es ist ganz einfach, Indizes zu ändern und zu sehen, welchen Unterschied es macht


3
@OMGPonies Der Schaden liegt im zusätzlichen Schreibaufwand in einer ausgelasteten Tabelle mit vielen Zeilen. Dies kann die Abfrageleistung tatsächlich verringern. Dies ist nur dann von Vorteil, wenn eine hohe Kardinalität vorliegt und die Abfragen so aufgebaut sind, dass sie die Vorteile nutzen.
Oucil

2

Ich denke, es würde helfen, wenn Sie eine Ansicht verwenden (wobei gelöscht = 0) und Sie regelmäßig von dieser Ansicht abfragen.


2

Ich denke , wenn Ihr boolean Feld so ist , dass man in vielen Fällen zu ihnen würde mit Bezug, wäre es sinnvoll , eine separate Tabelle zu haben, beispielsweise DeletedPages oder Special, die viele boolean Typ Felder haben, wie is_deleted, is_hidden, is_really_deleted, requires_higher_userusw, und dann würden Sie Joins nehmen, um sie zu bekommen.

In der Regel ist die Größe dieser Tabelle kleiner, und Sie erhalten einige Vorteile, wenn Sie Verknüpfungen verwenden, insbesondere was die Lesbarkeit und Wartbarkeit von Code betrifft. Und für diese Art von Abfrage:

select all pages where is_deleted = 1

Es wäre schneller, wenn es so implementiert würde:

select all pages where pages 
inner join DeletedPages on page.id=deleted_pages.page_id 

Ich glaube, ich habe irgendwo über MySQL-Datenbanken gelesen, dass Sie ein Feld benötigen, das mindestens eine Kardinalität von 3 hat, damit die Indizierung für dieses Feld funktioniert, aber bitte bestätigen Sie dies.


1
Angesichts der Tatsache, dass ein Boolescher Wert so dünn ist und wir keine Daten haben, ist es schwer zu sagen, aber wenn ein Join und sein Workflow entstehen, würde jede einzelne Abfrage Abfragen langsamer und nicht schneller machen, insbesondere wenn die Primärschlüssel anders geclustert würden und wenn die gelöschten Seiten Tabelle wurde für jede einzelne Abfrage benötigt.
Mark Canlas

0

Wenn Sie eine Datenbank verwenden, die Bitmap-Indizes unterstützt (z. B. Oracle), ist ein solcher Index für eine boolesche Spalte viel nützlicher als ohne.

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.