2015-02-04 15 views
21

In Mongodb gibt es mehrere Arten von index. Für diese Frage interessiere ich mich für die ascending (or descending) index, die für die Sortierung und die hash index verwendet werden kann, die laut der Dokumentation "primär mit sharded Clustern zur Unterstützung Hash-Shard-Schlüssel" (source) "eine gleichmäßigere Verteilung von Daten" (source)Mongodb Leistungsunterschied zwischen Hash und aufsteigende Indizes (Jeder Grund, nicht Hash in einem nicht geordneten Feld zu verwenden?)

ich weiß, dass Sie nicht einen Index wie erstellen: db.test.ensureIndex({ "key": "hashed", "sortOrder": 1 }) weil Sie einen Fehler

{ 
    "createdCollectionAutomatically" : true, 
    "numIndexesBefore" : 1, 
    "errmsg" : "exception: Currently only single field hashed index supported.", 
    "code" : 16763, 
    "ok" : 0 
} 

Meine Frage:

Zwischen den Indizes:

  1. db.test.ensureIndex({ "key": 1 })

  2. db.test.ensureIndex({ "key": "hashed" })

Für die Abfrage db.products.find({ key: "a" }), die eine leistungsfähigere ist ?, ist die hashed Schlüssel O(1)


Wie ich das bekam Frage:

Bevor ich wusste, dass Sie nicht Multi-Leitindizes mit hashed haben könnten, habe ich einen Index der Form db.test.ensureIndex({ "key": 1, "sortOrder": 1 }), und es während der Erstellung fragte ich mich, ob der Hash-Index performanter als der aufsteigende ein (Hash war in der Regel ist O(1)). Ich habe den Schlüssel so gelassen, wie es jetzt ist, weil (wie ich oben erwähnt habe) db.test.ensureIndex({ "key": "hashed", "sortOrder": 1 }) nicht erlaubt war. Aber die Frage, ob der Hash-Index schneller für die Suche nach einem Schlüssel ist, blieb mir in Erinnerung.

Die Situation, in der ich den Index gemacht war:

ich eine Sammlung hatte, die von Schlüsseln klassifiziert eine sortierte Liste von Dokumenten enthalten.

z.B. {key: a, sortOrder: 1, ...}, {key: a, sortOrder: 2, ...}, {key: a, sortOrder: 3, ...}, {key: b, sortOrder: 1, ...}, {key: b, sortOrder: 2, ...}, ...

Da ich die key verwendet zu klassifizieren und die sortOrder für Paginierung, I abgefragt immer mit einem Wert für die Filterung und die keysortOrder für den Auftrag der anwende Unterlagen.

Das bedeutet, dass ich zwei mögliche Anfragen hatte: db.products.find({ key: "a" }).limit(10).sort({"sortOrder", 1})

  • Und für die anderen Seiten db.products.find({ key: "a" , sortOrder: { $gt: 10 } }).limit(10).sort({"sortOrder", 1})
  • In diesem speziellen Szenario mit O(1) für den Schlüssel

    • Für die erste Seite suchen und O(log(n)) für die sortOrder wäre ideal gewesen, aber das war nicht erlaubt.

    +0

    Wenn ich darüber nachdenke, bin ich mir nicht sicher, ob der Hash im Schlüssel wirklich schneller ist als ein Binärbaum. Ich sage das, weil log2 (20.000.000) ~ = 25 und ich weiß nicht, ob eine gute Hash-Funktion viel schneller sein wird als das Überprüfen von weniger als 30 Zeigern. (In meinem Fall werde ich nicht über 20MM Schlüssel gehen viel) –

    +0

    Wenn Ihre App einfügen und löschen oft dann wahrscheinlich Hash-Index wird am besten – Robertiano

    +4

    Ich glaube, und ich werde dies überprüfen und aktualisieren, wenn ich falsch liege, dass ein Hash-Index ist ein getarnter Btree-Index. Die Btree-Schlüssel sind Hashwerte anstelle von Feldwerten. Daher gibt es keinen 'O (1) 'vs.' O (log n) 'asymptotischen Leistungssieg für Hashed-Indizes, da sie eigentlich Btrees sind, die Hashes speichern. Der Hauptzweck eines Hash-Index in MongoDB besteht darin, Schlüsselwerte gleichmäßig zu verteilen, so dass, wenn ein Hash-Index für '_id' als Shard-Schlüssel verwendet wird, Schreibvorgänge gleichmäßig unter Shards verteilt werden. – wdberkeley

    Antwort

    5

    Für die Abfrage db.products.find({ key: "a" }), welche ist performanter?

    das Feld Angesichts key in beiden Fällen indiziert ist, die Komplexitätsindex Suche selbst würde sehr ähnlich sein. Als der Wert a wäre , und in der Indexstruktur gespeichert.

    Wenn wir nach den Gesamtleistungskosten suchen, würde die Hash-Version zusätzliche (vernachlässigbare) Kosten verursachen, den Wert a zu hashen, bevor der Wert im Indexbaum übereinstimmt. Siehe auch mongo/db/index/hash_access_method.h

    Der Hash-Index konnte index prefix compression (WiredTiger) ebenfalls nicht verwenden. Index-Präfix-Komprimierung ist besonders effektiv für einige Datensätze, wie solche mit niedriger Kardinalität (z. B. Land) oder solche mit wiederkehrenden Werten wie Telefonnummern, Sozialversicherungscodes und Geo-Koordinaten. Es ist besonders effektiv für compound indexes, wo das erste Feld mit allen eindeutigen Werten des zweiten Feldes wiederholt wird.

    Gibt es einen Grund, Hash nicht in einem nicht geordneten Feld zu verwenden?

    Im Allgemeinen gibt es keinen Grund, einen Wert außerhalb des Bereichs zu hacken. Um einen Shard-Schlüssel auszuwählen, berücksichtigen Sie die Werte cardinality, frequency und rate of change des Werts.

    Der Hash-Index wird normalerweise für einen bestimmten Fall sharding verwendet. Wenn ein shard key Wert ein monotonically increasing/decreasing Wert ist, würde die Verteilung der Daten wahrscheinlich nur in einen Shard gehen. Hier könnte ein Hash-Shard-Schlüssel die Verteilung von Schreibvorgängen verbessern. Es ist eine kleine Abwägung, um Ihren Cluster zu verbessern. Siehe auch Hashed vs Ranged Sharding.

    ist es wert, einen zufälligen Hash oder Wert mit dem Dokument einzufügen, und das zum Teilen anstelle eines auf der _id erzeugten Hashes zu verwenden?

    Ob es sich lohnt, hängt vom Anwendungsfall ab. Ein benutzerdefinierter Hash-Wert würde bedeuten, dass jede Abfrage nach dem Hash-Wert einen benutzerdefinierten Hash-Code durchlaufen müsste, d. H. Eine Anwendung.

    Der Vorteil der Verwendung der integrierten Hash-Funktion besteht darin, dass MongoDB die Hashwerte automatisch berechnet, wenn Abfragen mit Hash-Indizes aufgelöst werden. Daher müssen Anwendungen keine Hashes berechnen.