Korrekte Indizierung bei Verwendung von OR-Operator

8

Ich habe eine Abfrage wie folgt:

%Vor%

Was wäre der richtige Weg, eine solche Tabelle für diese Abfrage zu indizieren?

Eine Abfrage wie diese dauert eine ganze Sekunde! Ich habe 1 Index mit allen 4 dieser Felder, also würde ich denken, dass mysql so etwas tun würde:

Gehen Sie jede Zeile im Index durch und denken dabei: Ist field1 etwas? Wie wäre es mit field2? Feld3? Feld4? Ok, nein, geh in die nächste Reihe.

    
James T 18.08.2011, 16:38
quelle

2 Antworten

15

Sie verstehen falsch, wie Indizes funktionieren.

Denken Sie an ein Telefonbuch (das Äquivalent eines zweispaltigen Indexes für den Nachnamen zuerst, der Vorname zuletzt). Wenn ich Sie auffordere, alle Personen im Telefonbuch zu finden, deren Nachname "Smith" ist, können Sie davon profitieren, dass die Namen auf diese Weise geordnet sind. Sie können davon ausgehen, dass die Smiths zusammen organisiert sind. Aber wenn ich dich auffordere, alle Leute zu finden, deren Vorname "John" ist, erhältst du keinen Nutzen aus dem Index. Johns kann jeden Nachnamen haben, und so sind sie überall im Buch verstreut und Sie müssen am Ende den harten Weg von der Titelseite zur Deckung suchen.

Wenn ich Sie nun bitten werde, alle Personen zu finden, deren Nachname "Smith" ODER deren Vorname "John" ist, können Sie die Smiths leicht finden wie zuvor, aber das hilft Ihnen nicht, die Johns zu finden . Sie sind immer noch im ganzen Buch verteilt und Sie müssen auf die harte Art nach ihnen suchen.

Das Gleiche gilt für mehrspaltige Indizes in SQL. Der Index wird nach der ersten Spalte sortiert, dann nach der zweiten Spalte in Fällen von Bindungen in der ersten Spalte sortiert und dann nach der dritten Spalte in Fällen von Bindungen in den ersten beiden Spalten usw. sortiert. Er ist nicht nach allen Spalten sortiert gleichzeitig. Daher hilft Ihr mehrspaltiger Index nicht dabei, Ihre Suchbegriffe effizienter zu machen, mit Ausnahme der Spalte ganz links im Index.

Zurück zu Ihrer ursprünglichen Frage.

  

Was wäre der richtige Weg, eine solche Tabelle für diese Abfrage zu indizieren?

Erstellen Sie einen separaten, einspaltigen Index für jede Spalte. Einer dieser Indizes wird eine bessere Wahl sein als die anderen, basierend auf der Schätzung von MySQL, wie viele ich es wert bin / O-Vorgänge wird der Index verwendet, wenn er verwendet wird.

Moderne Versionen von MySQL haben auch einige Tricks zum Zusammenführen von Indizes Daher kann die Abfrage mehr als einen Index in einer bestimmten Tabelle verwenden und dann versuchen, die Ergebnisse zusammenzuführen. Sonst beschränkt sich MySQL auf die Verwendung eines Indexes pro Tabelle in einer bestimmten Abfrage.

Ein weiterer Trick, den viele Leute erfolgreich verwenden, ist eine separate Abfrage für jede Ihrer indizierten Spalten (die den jeweiligen Index verwenden sollen) und dann UNION die Ergebnisse.

%Vor%

Eine abschließende Bemerkung: Wenn Sie in vier Feldern nach dem gleichen 'something' suchen, sollten Sie sich überlegen, ob alle vier Felder tatsächlich dasselbe sind, und Sie haben eine Tabelle entworfen, die verwirft das erste Normalformular mit sich wiederholenden Gruppen . Wenn ja, gehören field1 bis field4 in einer einzelnen Spalte in einer untergeordneten Tabelle. Dann wird es viel einfacher zu indizieren und abzufragen:

%Vor%     
Bill Karwin 18.08.2011, 17:11
quelle
0

Zusätzlich zum vorherigen Kommentar: Einige RDMS wie Mysql / PostgreSql können Indexzusammenführung verwenden, wenn Optimizer denkt, dass es eine gute Idee ist. Sie können also für jedes Feld verschiedene Indizes erstellen oder zusammengesetzte Indizes wie Feld1, Feld2 und Feld3, Feld4 erstellen. Schließlich sollten Sie mehrere verschiedene Lösungen ausprobieren und wählen Sie mit dem besten Plan erklären.

    
Andrej Ludinovskov 18.08.2011 17:17
quelle

Tags und Links

Django: Verwenden von Annotate, Count und Distinct in einem Queryset ___ qstntxt ___

Ich lese das Thema der Algorythmusanalyse. Hier ist der Textausschnitt aus dem Buch

  

Wenn sich n verdoppelt, erhöht sich die Laufzeit linear um den Faktor 2   Programme, 4 für quadratische Programme und 8 für kubische Programme.   Programme, die in logarithmischer Zeit laufen, nehmen nur eine additive Konstante   länger, wenn n sich verdoppelt, und Programme, die in O laufen (n log n)   etwas mehr als doppelt so lange, um unter den gleichen Umständen zu laufen.

     

Diese Erhöhungen können schwer zu erkennen sein, wenn die Terme niedrigerer Ordnung vorhanden sind   relativ große Koeffizienten und n ist nicht groß genug.

Meine Frage ist, was Autor bedeutet, dass Begriffe niedrigerer Ordnung relativ große Koeffizienten haben? Kann jemand mit Beispiel erklären

Danke!

    
___ answer7107229 ___

Die asymptotische Notation bezieht sich auf die Grenzen der Laufzeit als n- & gt; unendlich. Also kann eine Funktion, die O (n log n) ist, eine tatsächliche Laufzeit von .1 * n log n + 100000 * n haben.

In diesem Fall ist der Ausdruck 100000 * n der Ausdruck "niederer Ordnung". Als n- & gt; unendlich wird dieser Term durch den Term .1 * n log n übertroffen.

Wie Sie jedoch sehen können, wird der Wert 100000 * n für kleine n die Laufzeit dominieren.

    
___ tag123algorithm ___ Ein Algorithmus ist eine Folge wohldefinierter Schritte, die eine abstrakte Lösung für ein Problem definieren. Verwenden Sie dieses Tag, wenn sich Ihr Problem auf den Algorithmusentwurf bezieht. ___ answer7107221 ___

Wenn Sie zum Beispiel einen O (n) Algorithmus auf niedrigeren Skalen haben, könnten Sie T (n) = 490239n + (lächerliche Konstante einfügen) haben, was bedeutet, dass die Leistung schlecht aussehen würde, aber wenn die Skalen zunehmen, sehen Sie, dass Anstieg ist immer linear.

Das Beispiel der realen Welt ist merge sort, das O (n logn) -Problem ist, dass die Rekursion einen Rechenaufwand oder Overhead hat, der ein Faktor von n ist, der kleiner ist als nlogn, so dass er im Big-O verworfen wird dass dieser Faktor auch ziemlich groß wird und die Leistung beeinträchtigt.

    
___ answer7107245 ___

Angenommen, Ihr Algorithmus führt %code% Berechnungen tatsächlich aus, wenn er auf %code% -Elementen ausgeführt wird. Jetzt für %code% benötigen Sie 1001 Berechnungen, und für %code% brauchen Sie 2004. Der Unterschied zum linearen Wachstum ist winzig, und Sie können kaum den quadratischen Beitrag erkennen!

Asymptotisch jedoch benötigt Ihr Algorithmus O (n ^ 2) Schritte, so dass asymptotisch (wenn n groß wird) die Verdoppelung der Eingabegröße Ihre Laufzeit vervierfacht. Aber für unseren kleinen Wert hat die Verdopplung von 1 auf 2 die Laufzeit vervierfacht! Der Term niederer Ordnung ist %code% und sein Koeffizient (1000) ist groß im Vergleich zum Koeffizienten des Ausdrucks erster Ordnung %code% (der 1 ist).

Dies zeigt, wie die asymptotische Komplexität nichts über bestimmte, besonders kleine Werte aussagt. Es ist lediglich eine einschränkende Aussage über das Verhalten, wenn %code% groß wird.

    
___ answer7107262 ___

Wenn Sie die O-Notation verwenden, geben Sie den größten Ausdruck der Funktion an, die Ihre Leistungsgrenze ist. Wenn zum Beispiel die Leistung immer durch f = c 3 3 + c <2 n 2 + c <1> n + c <0> , Sie würden sagen, das ist O (n 3 ). Der Autor sagt, dass, wenn n klein ist, die Koeffizienten eine größere Auswirkung als n auf die Leistung haben können, beispielsweise wenn c2 sehr groß und c3 sehr klein ist , scheint die Leistung O (n 2 ) zu sein, bis die Größe von n die Koeffizienten dominiert, wenn man nur die relative Leistung für spezifische kleine Fälle von n betrachtet.

    
___