-
Hintergrund
-
Datenreduktionstechniken können angewendet werden, um die in einem Speichersystem gespeicherte Datenmenge zu reduzieren. Ein Beispiel für eine Technik zur Datenreduzierung ist die Datendeduplizierung. Die Datendeduplizierung identifiziert doppelte Dateneinheiten und versucht, die Anzahl der Instanzen doppelter Dateneinheiten, die im Speichersystem gespeichert sind, zu reduzieren oder zu eliminieren.
-
US 2020 / 0 089 788 A1 beschreibt eine Pufferbaumstruktur, die an jedem internen Knoten einen Puffer mit einem komprimierten Teil und einem nicht komprimierten Teil umfasst. Das Einfügen von Datenelementen in den Pufferbaum kann in Einheiten erfolgen, die als Pakete bezeichnet werden. Ein Paket wird zunächst im unkomprimierten Teil des Puffers eines empfangenden Knotens gespeichert. Wenn eine Komprimierungsauslösebedingung vorliegt, wird eine Paketkomprimierung einschließlich eines Datenelementkomprimierungsvorgangs durchgeführt. Eine Pufferentleerungsoperation (Flush) verschiebt die komprimierten Pakete an untergeordnete Knoten.
-
Dayan, Niv, et al.: Monkey: Optimal Navigable Key-Value Store, in: Proceedings of the 2017 ACM International Conference on Management of Data, 2017, S. 79-94, DOI: 10.1145/3035918.3064054, bezieht sich auf einen LSM-Baum-basierten Schlüsselwertspeicher.
-
Kurzbeschreibung
-
Es wird ein computerimplementiertes Verfahren gemäß Ansprüchen 1 bis 8, ein nicht-transitorisches maschinenlesbares Medium gemäß Ansprüchen 9 bis 14 und ein Speichersystem gemäß Ansprüchen 15 bis 20 offenbart.
-
Kurzbeschreibung der Zeichnungen
-
Einige Implementierungen werden mit Bezug auf die folgenden Abbildungen beschrieben.
- sind schematische Darstellungen von Beispielsystemen, gemäß einiger Implementierungen.
- ist eine Illustration eines Beispiel- Schlüssel-Wert-Indexes, in Übereinstimmung mit einigen Implementierungen.
- sind Illustrationen von Beispielknoten eines Schlüssel-Wert-Indexes, gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist ein Diagramm eines beispielhaften maschinenlesbaren Mediums, das Befehle in Übereinstimmung mit einigen Implementierungen speichert.
- ist ein schematisches Diagramm eines Beispiel-Computergeräts gemäß einiger Implementierungen.
- ist eine Illustration eines Beispielprozesses gemäß einiger Implementierungen.
- ist ein Diagramm eines beispielhaften maschinenlesbaren Mediums, das Befehle in Übereinstimmung mit einigen Implementierungen speichert.
- ist eine schematische Darstellung eines Beispiel-Rechengeräts gemäß einiger Implementierungen.
-
In den Zeichnungen bezeichnen identische Referenznummern ähnliche, aber nicht notwendigerweise identische, Elemente. Die Abbildungen sind nicht notwendigerweise maßstabsgetreu, und die Größe einiger Teile kann zur besseren Veranschaulichung des gezeigten Beispiels übertrieben sein. Darüber hinaus bieten die Zeichnungen Beispiele und/oder Implementierungen, die mit der Beschreibung übereinstimmen; die Beschreibung ist jedoch nicht auf die in den Zeichnungen dargestellten Beispiele und/oder Implementierungen beschränkt.
-
Detaillierte Beschreibung
-
In der vorliegenden Offenlegung schließt die Verwendung des Begriffs „ein“, „eine“ oder „die“ auch die Pluralformen ein, sofern aus dem Kontext nicht eindeutig etwas anderes hervorgeht. Auch der Begriff „beinhaltet“, „einschließlich“, „umfasst“, „mit“, „haben“ oder „mit“, wenn er in dieser Offenbarung verwendet wird, spezifiziert das Vorhandensein der angegebenen Elemente, schließt aber das Vorhandensein oder die Zugabe anderer Elemente nicht aus.
-
In einigen Beispielen verwenden Speichersysteme Indizes, um Beziehungen oder Zuordnungen zwischen Schlüsseln und Werten (hier auch als „Schlüssel-Wert-Paare“ bezeichnet) anzuzeigen. Ein Beispiel für die Verwendung eines Schlüssel-Wert-Index ist ein Speichersystem, das eine Datendeduplizierung auf der Grundlage von „Fingerabdrücken“ eingehender Dateneinheiten durchführt, wobei jeder Fingerabdruck eine bestimmte Dateneinheit identifiziert. Ein Fingerabdruck einer eingehenden Dateneinheit wird mit einem Fingerabdruck-Index verglichen, der ein Schlüssel-Wert-Index sein kann, in dem Fingerabdrücke die Schlüssel und die entsprechenden Datenpositionen die Werte sind. Eine Übereinstimmung zwischen dem Fingerabdruck und einem im Fingerabdruck-Index gespeicherten Fingerabdruck zeigt an, dass die eingehende Dateneinheit möglicherweise ein Duplikat einer bereits im Speichersystem gespeicherten Dateneinheit ist. Wenn die eingehende Dateneinheit ein Duplikat einer bereits gespeicherten Dateneinheit ist, kann, anstatt die doppelte eingehende Dateneinheit zu speichern, ein im Speichersystem gespeicherter Referenzzähler inkrementiert werden, um die Anzahl der empfangenen Instanzen der Dateneinheit anzuzeigen.
-
Ein „Fingerabdruck“ bezieht sich auf einen Wert, der durch Anwendung einer Funktion auf den Inhalt der Dateneinheit abgeleitet wird (wobei der „Inhalt“ die Gesamtheit oder eine Teilmenge des Inhalts der Dateneinheit umfassen kann). Ein Beispiel für eine Funktion, die angewendet werden kann, ist eine Hash-Funktion, die einen Hash-Wert auf der Grundlage der eingehenden Dateneinheit erzeugt. Beispiele für Hash-Funktionen sind kryptografische Hash-Funktionen wie die Secure Hash Algorithm 2 (SHA-2) Hash-Funktionen, z. B. SHA-224, SHA-256, SHA-384 usw. In anderen Beispielen können auch andere Arten von Hash-Funktionen oder andere Arten von Fingerabdruck-Funktionen verwendet werden.
-
Ein „Speichersystem“ kann ein Speichergerät oder ein Array von Speichergeräten umfassen. Ein Speichersystem kann auch einen oder mehrere Speicher-Controller enthalten, die den Zugriff auf das/die Speichergerät(e) verwalten. Eine „Dateneinheit“ kann sich auf jeden Teil der Daten beziehen, der im Speichersystem separat identifiziert werden kann. In einigen Fällen kann sich eine Dateneinheit auf einen Chunk, eine Sammlung von Chunks oder einen anderen Teil von Daten beziehen. In einigen Beispielen kann ein Speichersystem Dateneinheiten in einem persistenten Speicher speichern. Die persistente Speicherung kann mit einem oder mehreren persistenten (z. B. nichtflüchtigen) Speichergeräten, wie z. B. plattenbasierten Speichergeräten (z. B. Festplattenlaufwerken (HDDs)), Solid-State-Geräten (SSDs), wie z. B. Flash-Speichergeräten oder Ähnlichem, oder einer Kombination davon implementiert werden.
-
Ein „Controller“ kann sich auf eine Hardware-Verarbeitungsschaltung beziehen, die eine beliebige oder eine Kombination aus einem Mikroprozessor, einem Kern eines Multi-Core-Mikroprozessors, einem Mikrocontroller, einer programmierbaren integrierten Schaltung, einem programmierbaren Gate-Array, einem digitalen Signalprozessor oder einer anderen Hardware-Verarbeitungsschaltung umfassen kann. Alternativ kann sich ein „Controller“ auf eine Kombination aus einer Hardware-Verarbeitungsschaltung und maschinenlesbaren Anweisungen (Software und/oder Firmware) beziehen, die auf der Hardware-Verarbeitungsschaltung ausführbar sind.
-
In einigen Beispielen kann ein Schlüssel-Wert-Index in Form eines B-Baum-Index vorliegen, der hierarchisch angeordnete Knoten enthält. Blattknoten des B-Baum-Index enthalten Einträge, die Schlüssel auf Werte abbilden. In einem Deduplizierungssystem bilden die Blattknoten des B-Baum-Index beispielsweise Fingerabdrücke auf Speicherplatzindikatoren ab (z. B. eine fortlaufende Blocknummer). Interne Knoten des B-Baum-Index können verwendet werden, um einen passenden Eintrag des B-Baum-Index basierend auf einem Schlüssel zu finden. Die Verwendung eines B-Baum-Index kann jedoch mit verschiedenen Problemen verbunden sein. Beispielsweise kann das Aktualisieren eines B-Baum-Index, um ein neues Schlüssel-Wert-Paar aufzunehmen, das Laden eines gesamten Blattknotens des B-Baum-Index aus dem permanenten Speicher in den Speicher, die Verarbeitung des Blattknotens, um das neue Schlüssel-Wert-Paar einzufügen, und das erneute Schreiben des gesamten Blattknotens in den permanenten Speicher erfordern. Darüber hinaus kann eine solche Aktualisierung auch ein ähnliches Laden, Verarbeiten und Neuschreiben mehrerer interner Knoten beinhalten, um die Position des neuen Schlüssel-Wert-Paares wiederzugeben. Daher kann jede Indexaktualisierung eine erhebliche Menge an Speicher-, CPU- und Festplattenbandbreiten-Overhead in Verbindung mit Eingabe-/Ausgabeoperationen des permanenten Speichers verbrauchen. Der mit Indexaktualisierungen verbundene Overhead wird hier als „Schreibverstärkung“ bezeichnet.
-
In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung kann ein Schlüssel-Wert-Index statt in einem B-Baum in einer Baumstruktur gespeichert werden, in der jeder interne Knoten (hier als „indirekter“ Knoten bezeichnet) einen Puffer zum Speichern von Schlüssel-Wert-Paaren enthalten kann (auch als „Knotenpuffer“ bezeichnet). Der Puffer eines indirekten Knotens speichert die Schlüssel-Wert-Paare so lange, bis ein Schwellenwert für den Puffer erreicht ist, was dazu führen kann, dass alle gespeicherten Schlüssel-Wert-Paare in einem einzigen Übertragungsvorgang an untergeordnete Knoten übertragen werden. In einigen Beispielen kann die Massenübertragung von Schlüssel-Wert-Paaren von einem Quellknoten an untergeordnete Knoten (z. B. andere indirekte Knoten oder Blattknoten) die Anzahl der Übertragungs- und Aktualisierungsvorgänge zwischen dem Speicher und dem permanenten Speicher reduzieren und somit die mit dem Schlüssel-Wert-Index verbundene Schreibverstärkung verringern.
-
Das Lesen von Schlüssel-Wert-Paar-Daten aus dem Schlüssel-Wert-Index kann jedoch das Laden des Puffers jedes Knotens in den Speicher und die Suche nach dem Schlüssel in dem in den Speicher geladenen Puffer erfordern. Als solches kann das Lesen von Daten jedes Schlüssel-Wert-Paares auch eine erhebliche Menge an Speicher und Bandbreite verbrauchen (hier als „Leseverstärkung“ bezeichnet). In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung kann jeder Knoten eines Schlüssel-Wert-Index einen Bloom-Filter und Fence-Zeiger enthalten. In einigen Beispielen wird ein Puffer eines Knotens nach einem bestimmten Schlüssel durchsucht, wenn der Bloom-Filter des Knotens anzeigt, dass der bestimmte Schlüssel in dem Puffer gespeichert ist. Auf diese Weise kann der Bloom-Filter verwendet werden, um das Laden des Puffers in den Speicher zu vermeiden und dadurch die mit dem Lesen des Schlüssel-Wert-Paares verbundene Leseverstärkung zu reduzieren.
-
In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung kann der Puffer eines Knotens in Segmente oder „Puffer-Blöcke“ unterteilt sein. Ferner kann in einigen Beispielen jeder Fence-Zeiger des Knotens die untere Grenze der Schlüsselwerte anzeigen, die in einem entsprechenden Puffer-Block enthalten sind. In anderen Beispielen kann der Fence-Zeiger die Obergrenze der Schlüsselwerte angeben, die in dem entsprechenden Puffer-Block enthalten sind. Wenn der Bloom-Filter anzeigt, dass das Schlüssel-Wert-Paar im Puffer gespeichert ist, können die Fence-Zeiger verwendet werden, um einen bestimmten Puffer-Block zu identifizieren, in dem das Schlüssel-Wert-Paar wahrscheinlich gespeichert ist. Anstatt den gesamten Puffer in den Speicher zu laden, wird nur der identifizierte Puffer-Block in den Speicher geladen. Auf diese Weise kann die Verwendung der Fence-Zeiger die Leseverstärkung reduzieren.
-
In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung können die Knotenpuffer des Index entsprechend der entsprechenden Ebene im Index dimensioniert werden. In einigen Beispielen wird das Verhältnis der Gesamtpuffergröße in einer bestimmten Ebene zur Gesamtpuffergröße auf der nächstniedrigeren Ebene (d. h. eine Ebene näher an den Blattknoten) auf einen vordefinierten Wert gesetzt. Der Wert dieses Verhältnisses kann von einem Benutzer eingestellt werden, um den Grad der mit dem Index verbundenen Schreibverstärkung abzustimmen.
-
In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung können die Bloom-Filter auf verschiedenen Ebenen des Index so dimensioniert werden, dass die Bloom-Filter in den Knoten auf höheren Ebenen (d. h. näher am Wurzelknoten) mit relativ niedrigeren Falsch-Positiv-Quoten verbunden sind als diejenigen auf niedrigeren Ebenen (d. h. näher an den Blattknoten). Auf diese Weise kann der mit Bloom-Filtern verbundene Speicherverbrauch optimiert werden.
-
In Übereinstimmung mit einigen Implementierungen der vorliegenden Offenlegung kann die Verdichtung jedes indirekten Knotens als Hintergrundprozess ausgeführt werden, wobei das Hinzufügen zusätzlicher Einträge zum Puffer auch dann möglich ist, wenn die Verdichtung dadurch ausgelöst wird, dass der Pufferfüllstand (d. h. die Menge der im Puffer gespeicherten Daten) den Schwellenwert des Puffers erreicht. Die Priorität des Hintergrundprozesses kann mehrfach erhöht werden, wenn der Pufferfüllstand über den Schwellenwert ansteigt. Auf diese Weise können Aktualisierungen des Indexes fortgesetzt werden, ohne die Nutzung des Knotens zu unterbrechen.
-
Gemäß einigen Implementierungen der vorliegenden Offenlegung kann als Reaktion auf die Erkennung eines Ladevorgangs mehrerer sequenzieller Schlüssel-Wert-Paare in den Index der Betrieb des Index vorübergehend geändert werden, um sich während der Verarbeitung des sequenziellen Ladevorgangs wie ein B-Baum zu verhalten. Diese temporäre Änderung kann einen effizienteren Betrieb während sequenzieller Ladevorgänge ermöglichen.
-
1. Speichersystem inklusive Schlüssel-Wert-Index mit Knotenpuffern
-
zeigt ein Beispiel für ein Speichersystem 100, das gemäß einigen Implementierungen einen Speicher-Controller 110 und einen persistenten Speicher 140 enthält. Wie dargestellt, kann der Speicher-Controller 110 eine Update-Engine 120, eine Merge-Engine 150, einen Speicher 130 und eine Abfrage-Engine 160 enthalten. In einigen Beispielen kann der Speicher 130 einen Aktualisierungspuffer 135 enthalten, und der dauerhafte Speicher 140 kann einen Schlüssel-Wert-Index 145 enthalten. In einigen Implementierungen kann der Schlüssel-Wert-Index 145 Schlüsselwertdaten enthalten, die als Knotenbaum organisiert sind. Eine Beispielimplementierung des Schlüssel-Wert-Indexes 145 wird im Folgenden unter Bezugnahme auf beschrieben. In einigen Beispielen kann der dauerhafte Speicher 140 ein oder mehrere nicht transitorische Speichermedien wie Festplattenlaufwerke (HDDs), Solid-State-Laufwerke (SSDs), optische Festplatten usw. oder eine Kombination davon umfassen. Der Speicher 130 kann Halbleiterspeichergeräte wie dynamische oder statische Direktzugriffsspeicher (DRAMs oder SRAMs), nichtflüchtige Dual-Inline-Speichermodule (NVDIMMs) usw. umfassen.
-
In einigen Implementierungen kann die Update-Engine 120 eine Aktualisierung 105 für den Schlüssel-Wert-Index 145 im permanenten Speicher 140 empfangen. Zum Beispiel kann jede Aktualisierung 105 ein Schlüssel-Wert-Paar sein, das dem Schlüssel-Wert-Index 145 hinzugefügt werden soll. In einigen Beispielen kann die Update-Engine 120 alle oder einen Teil der Aktualisierung 105 in einem Aktualisierungspuffer 135 speichern, der im Speicher 130 abgelegt ist. Außerdem kann die Merge-Engine 150 den Schlüssel-Wert-Index 145 mit Schlüssel-Wert-Paaren aktualisieren, die im Aktualisierungspuffer 135 gespeichert sind. Beachten Sie, dass, obwohl in nur ein Aktualisierungspuffer 135 dargestellt ist, die Speicher-Controller 110 in anderen Beispielen mehrere Aktualisierungspuffer 135 enthalten kann. In einigen Beispielen kann der Speicher 130 in einem oder mehreren flüchtigen Speichergeräten implementiert sein.
-
In einigen Implementierungen kann die Abfrage-Engine 160 eine Abfrage 165 empfangen, die einen bestimmten Schlüssel spezifiziert, und auf den Schlüssel-Wert-Index 145 (und den Aktualisierungspuffer 135 in einigen Beispielen) zugreifen oder mit ihm interagieren, um den Wert zu bestimmen, der mit dem in der Abfrage 165 spezifizierten Schlüssel übereinstimmt. Ferner kann die Abfrage-Engine 160 den passenden Wert als Antwort auf die Abfrage 165 zurückgeben. In einigen Beispielen kann die Abfrage 165 eine vom Benutzer erstellte Abfrage sein (z. B. eine SQL-Abfrage, eine Leseanforderung für ein Datenelement usw.).
-
Wie hier verwendet, kann sich eine „Engine“ auf eine Hardware-Verarbeitungsschaltung beziehen, die eine beliebige oder eine Kombination aus einem Mikroprozessor, einem Kern eines Multi-Core-Mikroprozessors, einem Mikrocontroller, einer programmierbaren integrierten Schaltung, einem programmierbaren Gate-Array, einem digitalen Signalprozessor oder einer anderen Hardware-Verarbeitungsschaltung umfassen kann. Alternativ kann sich eine „Engine“ auf eine Kombination aus einer Hardware-Verarbeitungsschaltung und maschinenlesbaren Anweisungen (Software-Anweisungen und/oder Firmware-Anweisungen, die auf mindestens einem maschinenlesbaren Speichermedium gespeichert sind) beziehen, die auf der Hardware-Verarbeitungsschaltung ausführbar sind.
-
In ist ein Beispiel für ein Speichersystem 102 dargestellt, das zur Datendeduplizierung verwendet wird. Die Elemente des Speichersystems 102, die dieselben Referenznummern des Speichersystems 100 (dargestellt in haben, bezeichnen ähnliche, aber nicht unbedingt identische Elemente. Wie gezeigt, kann im Speichersystem 102 der Speicher-Controller 117 eine Deduplizierungs-Engine 127 enthalten, und der persistente Speicher 140 kann einen Fingerabdruck-Index 147 enthalten. Der Fingerabdruck-Index 147 kann im Allgemeinen einer Beispielimplementierung des persistenten Index 145 (dargestellt in entsprechen. Ferner kann die Dateneinheit 107 eine eingehende Dateneinheit sein, die mit Schreibanforderungen zum Schreiben von Daten in das Speichersystem 102 verbunden ist. In einigen Beispielen kann eine Fingerabdruck-Indexaktualisierung (oder äquivalent dazu ein „Fingerabdruck-Indexeintrag“) für die Dateneinheit 107 einen Fingerabdruck und/oder einen entsprechenden Speicherplatzindikator für die Dateneinheit 107 enthalten. In solchen Beispielen kann der Fingerabdruck-Index 147 mehrere Fingerabdrücke und entsprechende Speicherplatzdaten speichern.
-
In einigen Implementierungen kann die Deduplizierungs-Engine 127 einen Fingerabdruck basierend auf der Dateneinheit 107 erzeugen. In einigen Beispielen kann ein von der Deduplizierungs-Engine 127 erzeugter Fingerabdruck einen vollständigen oder teilweisen Hash-Wert basierend auf der Dateneinheit 107 enthalten. In anderen Beispielen kann die Deduplizierungs-Engine 127 einen anderen Typ von Fingerabdruck erzeugen.
-
In einigen Implementierungen kann die Deduplizierungs-Engine 127 basierend auf dem Fingerabdruck-Index 147 bestimmen, ob das Speichersystem 102 tatsächlich ein Duplikat der eingehenden Dateneinheit 107 enthält oder nicht. Genauer gesagt, kann die Deduplizierungs-Engine 127 den für die Dateneinheit 107 erzeugten Fingerabdruck mit gespeicherten Fingerabdrücken im Fingerabdruck-Index 147 vergleichen. Wenn der erzeugte Fingerabdruck mit einem gespeicherten Fingerabdruck übereinstimmt, dann kann die Deduplizierungs-Engine 127 feststellen, dass ein Duplikat der eingehenden Dateneinheit 107 bereits im Speichersystem 102 gespeichert ist. Als Ergebnis kann die Deduplizierungs-Engine 127 entscheiden, die eingehende Dateneinheit 107 nicht zu speichern und stattdessen eine Zählung der Anzahl der Dateneinheiten zu aktualisieren, die den übereinstimmenden Fingerabdruck teilen. Andererseits, wenn der für die eingehende Dateneinheit 107 berechnete Fingerabdruck mit keinem Fingerabdruck im Fingerabdruck-Index 147 übereinstimmt, dann kann die Deduplizierungs-Engine 127 feststellen, dass das Speichersystem 100 kein Duplikat der Dateneinheit 107 speichert, und als Reaktion darauf die Dateneinheit 107 neu im Speichersystem 102 speichern.
-
2. Beispiel für einen Schlüssel-Wert-Index mit Knotenpuffern
-
zeigt eine Illustration eines Beispiel- Schlüssel-Wert-Indexes 200, in Übereinstimmung mit einigen Implementierungen. In einigen Beispielen kann der Schlüssel-Wert-Index 200 allgemein einer Beispielimplementierung des Schlüssel-Wert-Index 145 (dargestellt in und/oder des Fingerabdruck-Index 147 (dargestellt in entsprechen. Ferner kann in einigen Beispielen der Schlüssel-Wert-Index 200 von dem Speicher-Controller 110 (dargestellt in und/oder dem Speicher-Controller 117 (dargestellt in erzeugt werden. In einigen Beispielen kann der Schlüssel-Wert-Index 200 Fingerabdrücke von Dateneinheiten auf Orte dieser Dateneinheiten abbilden. In anderen Beispielen kann der Schlüssel-Wert-Index 200 ein Blockindex sein, der einen Datenträger oder einen Offset auf eine Kombination aus einem Generationsbezeichner (z. B. eine Versionsnummer eines Snapshots des Datenträgers) und einem Speicherplatzbezeichner (z. B. eine fortlaufende Blocknummer) abbildet. In noch anderen Beispielen kann der Schlüssel-Wert-Index 200 ein Festplattenindex sein, der verschiedene Arten von Blöcken auf ihre Festplattenpositionen abbildet (z. B. Abbildung der Speicherortkennung auf die Festplattenposition des Blocks, Abbildung einer Kombination aus Erzeugungskennung und Offset auf die Festplattenposition usw.), zusammen mit anderen Informationen (z. B. einem vollständigen Fingerabdruck, einer komprimierten Größe des Blocks usw.). In einem weiteren Beispiel kann der Schlüssel-Wert-Index 200 ein Cache-Index sein, der eine Kombination aus einem Generationsbezeichner und einem benutzerdefinierten Wert auf eine Kombination aus einer Blockposition des Blocks und einer komprimierten Größe abbildet. Andere Kombinationen der obigen Punkte oder Variationen davon sind ebenfalls möglich.
-
Wie in dargestellt, kann der Schlüssel-Wert-Index 200 in einer Baumstruktur mit mehreren Knoten angeordnet sein. Die Knoten können in verschiedenen Ebenen organisiert sein, die Eltern-Kind-Beziehungen bilden. Beispielsweise kann eine erste Ebene 210 einen Wurzelknoten 211 enthalten, und eine zweite Ebene 220 kann indirekte Knoten 221-224 enthalten, die Kinder des Wurzelknotens 211 sind. Ferner kann eine dritte Ebene 230 indirekte Knoten 231-234 enthalten, die Kinder des indirekten Knotens 222 (in der zweiten Ebene 220) sind, und eine vierte Ebene 240 kann Blattknoten 241-244 enthalten, die Kinder des indirekten Knotens 233 (in der dritten Ebene 230) sind. In einigen Beispielen kann die Anzahl der untergeordneten Knoten, die mit jedem übergeordneten Knoten verbunden sind, durch einen Fan-Out-Parameter angegeben werden, der dem Schlüssel-Wert-Index 200 zugeordnet ist.
-
In den vorliegenden Beispielen kann jeder Knoten eines Schlüssel-Wert-Indexes entweder ein Blattknoten oder ein indirekter Knoten sein (d. h. ein beliebiger Knoten außer einem Blattknoten, einschließlich des Wurzelknotens). In einigen Implementierungen kann jeder indirekte Knoten des Schlüssel-Wert-Index 200 (z. B. Wurzelknoten 211, indirekte Knoten 221-224, indirekte Knoten 231-234) einen Puffer (hier auch als „Knotenpuffer“ bezeichnet und in nicht dargestellt) zum Speichern von Schlüsselwertdaten enthalten. In einigen Beispielen kann jeder Blattknoten des Schlüssel-Wert-Index 200 Schlüsselwertdaten speichern. Eine Beispielimplementierung eines indirekten Knotens, der einen Knotenpuffer enthält, wird im Folgenden unter Bezugnahme auf beschrieben.
-
In einigen Implementierungen können die Knoten des Schlüssel-Wert-Index 200 schrittweise von oben nach unten in der Baumstruktur erzeugt werden. Bei der Initialisierung des Schlüssel-Wert-Index 200 (z. B. bei der ersten Verwendung) kann der Schlüssel-Wert-Index 200 beispielsweise nur den Wurzelknoten 211 enthalten. In diesem Beispiel können die Schlüssel-Wert-Paare, die dem Schlüssel-Wert-Index 200 hinzugefügt werden, in einem Knotenpuffer des Wurzelknotens 211 gespeichert werden.
-
In einigen Implementierungen kann ein Verdichtungsprozess ausgelöst werden, wenn die im Knotenpuffer des Wurzelknotens 211 gespeicherten Schlüsselwertdaten einen Schwellenwert erreichen (z. B. eine bestimmte Anzahl gespeicherter Schlüssel-Wert-Paare, einen bestimmten Prozentsatz der Gesamtkapazität usw.). Wie hier verwendet, kann sich „Verdichtung“ auf die Übertragung von Schlüsselwertdaten von einem übergeordneten Knoten zu einem oder mehreren untergeordneten Knoten beziehen. In einigen Beispielen können bei der ersten Verdichtung des Wurzelknotens 211 die indirekten Knoten 221-224 (d. h. die unmittelbaren Kinder des Wurzelknotens 211) erzeugt werden. Außerdem können bei jeder Verdichtung des Wurzelknotens 211 die im Knotenpuffer des Wurzelknotens 211 gespeicherten Schlüsselwertdaten an die Knotenpuffer der indirekten Knoten 221-224 übertragen werden. Wie hierin verwendet, bezieht sich „Übertragen“ von Daten auf das Verschieben der Daten zu einem Zielknoten, so dass die Daten nicht mehr in einem Quellknoten vorhanden sind. In einigen Beispielen kann jeder der indirekten Knoten 221-224 mit einem anderen Teil des Bereichs von Schlüsseln im Knotenpuffer des Wurzelknotens 211 verbunden sein. Dementsprechend kann in solchen Beispielen jedes der Schlüssel-Wert-Paare des Wurzelknotens 211 auf einen anderen der untergeordneten Knoten 221-224 verteilt werden, und zwar entsprechend dem Bereich, der jedem untergeordneten Knoten zugeordnet ist. Sobald die Verdichtung des Wurzelknotens 211 abgeschlossen ist, ist der Knotenpuffer des Wurzelknotens 211 leer, und danach werden alle neuen Schlüsselwertaktualisierungen, die am Stammknoten 211 empfangen werden, im Knotenpuffer des Wurzelknotens 211 gespeichert.
-
In einigen Implementierungen kann der oben beschriebene Verdichtungsprozess in ähnlicher Weise für jeden indirekten Knoten wiederholt werden. Wenn beispielsweise der indirekte Knoten 222 zum ersten Mal verdichtet wird (d. h. wenn der Knotenpuffer des indirekten Knotens 222 einen Schwellenwert erreicht), können die indirekten Knoten 231-234 (d. h. die unmittelbaren Kinder des indirekten Knotens 222) erzeugt werden, und die im Knotenpuffer des indirekten Knotens 222 gespeicherten Schlüsselwertdaten können in die Knotenpuffer der indirekten Knoten 231-234 übertragen werden. In einem anderen Beispiel können bei der ersten Verdichtung des indirekten Knotens 233 die Blattknoten 241-244 (d. h. die unmittelbaren Kinder des indirekten Knotens 233) erzeugt werden, und die im Knotenpuffer des indirekten Knotens 233 gespeicherten Schlüsselwertdaten können an die Blattknoten 241-244 übertragen werden.
-
In einigen Implementierungen kann der Schlüssel-Wert-Index 200 jeden Schlüssel und den entsprechenden Wert als zwei separate gespeicherte Elemente speichern. Allerdings sind die Implementierungen in dieser Hinsicht nicht beschränkt. In einigen Implementierungen kann der Schlüssel beispielsweise durch den Offset oder die Position des entsprechenden Wertes innerhalb eines Knotens oder Speicherelements impliziert oder angezeigt werden. In solchen Implementierungen kann sich ein „Schlüssel-Wert-Paar“ auf einen gespeicherten Wert beziehen, der mit einem impliziten Schlüssel verbunden ist.
-
Beachten Sie, dass andere indirekte Knoten in verschiedenen Ebenen des Schlüssel-Wert-Index 200 untergeordnete Knoten haben können, obwohl dies in aus Gründen der Übersichtlichkeit nicht dargestellt ist. Zum Beispiel könnte der indirekte Knoten 221 mehrere untergeordnete Knoten in der dritten Ebene 230 haben, der indirekte Knoten 234 könnte mehrere untergeordnete Knoten in der vierten Ebene 240 haben, und so weiter im Laufe der Zeit im gesamten Schlüssel-Wert-Index 200.
-
3. Beispielknoten des Schlüssel-Wert-Index
-
zeigt eine Illustration eines beispielhaften indirekten Knotens 300 in Übereinstimmung mit einigen Implementierungen. Der indirekte Knoten 300 kann im Allgemeinen einer Beispielimplementierung eines der in dargestellten indirekten Knoten entsprechen (z. B. Wurzelknoten 211, indirekte Knoten 221-224 und/oder indirekte Knoten 231-234). Wie in gezeigt, kann der indirekte Knoten 300 einige oder alle untergeordneten Zeiger 310, Fence-Zeiger 320, einen Bloom-Filter 330 und/oder einen Knotenpuffer 340 enthalten.
-
In einigen Implementierungen kann der Knotenpuffer 340 mehrere Puffer-Blöcke 345A-345N (hier auch als „Puffer-Blöcke 345" bezeichnet) enthalten, um Schlüssel-Wert-Daten zu speichern (z. B. einen Fingerabdruck einer Dateneinheit und einen entsprechenden Speicherplatzindikator für diese Dateneinheit 107). Die Puffer-Blöcke 345A-345N können in der Reihenfolge der Schlüssel angeordnet sein (z. B. in numerischer Reihenfolge, in alphabetischer Reihenfolge usw.). Beispielsweise kann der Puffer-Block 345A Schlüsselwertdaten für einen niedrigsten Bereich von Schlüsseln speichern, während der Puffer-Block 345N Schlüsselwertdaten für einen höchsten Bereich von Schlüsseln speichern kann. In einigen Beispielen kann jeder der Puffer-Blöcke 345 gleich oder ähnlich groß sein (z. B. 32 kb, 64kb usw.). In einigen Implementierungen kann die Größe des Knotenpuffers 340 basierend auf einem Ebenenverhältnis bestimmt werden. In einigen Beispielen kann das Ebenenverhältnis ein festes Verhältnis zwischen den Gesamtpuffergrößen in zwei benachbarten Ebenen eines Schlüssel-Wert-Indexes sein. Darüber hinaus kann das Ebenenverhältnis auf der Grundlage von benutzerdefinierten Parametern bestimmt werden, um das Niveau der Schreibverstärkung abzustimmen, die mit dem Schlüssel-Wert-Index verbunden ist.
-
In einigen Implementierungen können die untergeordneten Zeiger 310 auf alle Knoten zeigen oder diese anderweitig identifizieren, die unmittelbare untergeordnete Knoten des indirekten Knotens 300 sind. Beispielsweise kann der Wurzelknoten 211 unter Bezugnahme auf den (in dargestellten) Schlüssel-Wert-Index 200 entsprechende untergeordnete Zeiger 310 enthalten, die auf jeden der indirekten Knoten 221-224 (d. h. die unmittelbaren untergeordneten Knoten des Wurzelknotens 211) zeigen. In einigen Beispielen können die untergeordneten Zeiger 310 das erste Mal erzeugt werden, wenn der indirekte Knoten 300 verdichtet wird (z. B. wenn der Knotenpuffer 340 einen vordefinierten Schwellenwert erreicht).
-
In einigen Implementierungen kann der Bloom-Filter 330 die Bestimmung ermöglichen, welche Schlüssel nicht im Knotenpuffer 340 enthalten sind und welche Schlüssel im Knotenpuffer 340 enthalten sein könnten (d. h., mit der Möglichkeit von falsch-positiven Meldungen). Anders ausgedrückt, der Bloom-Filter 330 zeigt die Schlüssel an, die nicht im Knotenpuffer 340 enthalten sind, und zeigt die Schlüssel an, die im Knotenpuffer 340 enthalten sein könnten, wobei die Möglichkeit besteht, dass er zumindest für einige Schlüssel eine falschpositive Anzeige liefert (d. h. anzeigt, dass ein Schlüssel im Knotenpuffer 340 enthalten ist, obwohl er es nicht ist). Wenn der Bloom-Filter 330 anzeigt, dass ein bestimmter Schlüssel nicht im Knotenpuffer 340 enthalten ist, ist es dementsprechend möglich, Verarbeitungszeit und/oder Bandbreite zu vermeiden, die mit dem Laden dieses Knotenpuffers 340 in den Speicher und der Suche nach diesem bestimmten Schlüssel verbunden sind, da die Verwendung des Bloom-Filters 330 genau anzeigen kann, wenn der Schlüssel nicht im Knotenpuffer 340 enthalten ist. Wenn der Bloom-Filter 330 dagegen anzeigt, dass ein bestimmter Schlüssel im Knotenpuffer 340 enthalten ist, kann der Knotenpuffer 340 dann nach diesem bestimmten Schlüssel durchsucht werden. In einigen Implementierungen kann die Größe des Bloom-Filters 330 so bemessen sein, dass die Bloom-Filter 330 in Knoten auf höheren Ebenen relativ größer sind als die auf niedrigeren Ebenen.
-
In einigen Implementierungen können beim Durchsuchen des Knotenpuffers 340 nach einem bestimmten Schlüssel die Fence-Zeiger 320 verwendet werden, um einen bestimmten Puffer-Block 345 zu identifizieren, der wahrscheinlich Daten speichert, die dem bestimmten Schlüssel zugeordnet sind. In einigen Beispielen können die Fence-Zeiger 320 die niedrigsten und/oder höchsten Schlüsselwerte jedes Puffer-Blocks 345 identifizieren. Zum Beispiel kann jeder Fence-Zeiger 320 die untere Grenze der Schlüsselwerte identifizieren, die in einem entsprechenden Puffer-Block 345 enthalten sind. Daher können die Fence-Zeiger 320 verwendet werden, um zu identifizieren, welcher Puffer-Block 345 den Schlüsselbereich enthält, in den der gesuchte Schlüssel fällt. Anstatt den gesamten Knotenpuffer 340 in den Speicher zu laden, muss dementsprechend nur der identifizierte Puffer-Block 345 in den Speicher geladen werden. Auf diese Weise können die Fence-Zeiger 320 die Leseverstärkung in Verbindung mit dem indirekten Knoten 300 reduzieren.
-
In einigen Implementierungen können die Puffer-Blöcke 345 zusammen oder in separaten Datenblöcken gespeichert werden. Außerdem können die Puffer-Blöcke 345 getrennt von den übrigen Elementen des indirekten Knotens 300 (d. h. von den untergeordneten Zeigern 310, den Fence-Zeigern 320 und/oder dem Bloom-Filter 330) gespeichert werden. In einigen Beispielen können die untergeordneten Zeiger 310, die Fence-Zeiger 320 und der Bloom-Filter 330 in den Speicher geladen werden, bevor einer der Puffer-Blöcke 345 in den Speicher geladen wird. Wenn der Bloom-Filter 330 anzeigt, dass ein gesuchter Schlüssel im Knotenpuffer 340 enthalten ist, können die Fence-Zeiger 320 zur Identifizierung eines einzelnen Puffer-Blocks 345 verwendet werden, und nur dieser identifizierte Puffer-Block 345 wird dann in den Speicher geladen.
-
zeigt eine Illustration eines Beispiel-Blattknotens 350 in Übereinstimmung mit einigen Implementierungen. Der Blattknoten 350 kann im Allgemeinen einer Beispielimplementierung eines der in gezeigten Blattknoten entsprechen (z. B. Blattknoten 241-244). Wie in dargestellt, kann der Blattknoten 350 Schlüsselwertdaten 360 enthalten.
-
4. Verdichtungsprozess im Schlüssel-Wert-Index
-
zeigt einen Beispielprozess 400, gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 400 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 400 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Prozesses 400 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 410 kann den Empfang einer Schreibanforderung beinhalten, um ein Schlüssel-Wert-Paar zu einem Index hinzuzufügen. Beispielsweise kann die Update-Engine 120 die Aktualisierung 105 im Aktualisierungspuffer 135 speichern, und die Merge-Engine 150 kann den Schlüssel-Wert-Index 145 mit den im Aktualisierungspuffer 135 gespeicherten Schlüssel-Wert-Paar-Daten aktualisieren (siehe . In einigen Beispielen kann der Schlüssel-Wert-Index 145 in einer Baumstruktur mit mehreren Knoten angeordnet sein. Ferner kann der Schlüssel-Wert-Index 145 in einigen Beispielen Fingerabdrücke von Dateneinheiten auf Orte dieser Dateneinheiten abbilden.
-
Block 420 kann das Speichern des Schlüssel-Wert-Paares in einem Knotenpuffer eines indirekten Knotens des Indexes beinhalten. Nehmen wir an, dass im Beispiel von der indirekte Knoten mehr als eine Ebene über allen Blattknoten liegt. Anders ausgedrückt: Im Beispiel von sind alle untergeordneten Knoten des indirekten Knotens, der das Schlüssel-Wert-Paar speichert (in Block 420), ebenfalls indirekte Knoten. Zum Beispiel, bezogen auf die , kann die Speicher-Controller 110 und/oder die Merge-Engine 150 das empfangene Schlüssel-Wert-Paar im Knotenpuffer 340 des Wurzelknotens 211 speichern. In einigen Beispielen kann ein Bloom-Filter 330 des Wurzelknotens 211 so konfiguriert sein (z. B. durch Setzen von Bitwerten), dass er anzeigt, dass das empfangene Schlüssel-Wert-Paar im Knotenpuffer 340 des Wurzelknotens 211 gespeichert ist.
-
Die Raute 430 kann die Bestimmung beinhalten, ob der Knotenpuffer des indirekten Knotens einen vordefinierten Schwellenwert überschreitet. Wenn festgestellt wird, dass der Knotenpuffer den Schwellenwert nicht überschreitet, kann der Prozess 400 zu Block 410 zurückkehren (d. h., um ein weiteres Schlüssel-Wert-Paar zu empfangen). Zum Beispiel, bezogen auf die , kann die Speicher-Controller 110 feststellen, ob der Knotenpuffer 340 des Wurzelknotens 211 einen vordefinierten Füllstand überschreitet (z. B. 90 % voll, 100 % voll, eine bestimmte Anzahl von Schlüssel-Wert-Paaren usw.).
-
Wenn jedoch an der Raute 430 festgestellt wird, dass der Knotenpuffer den Schwellenwert überschreitet, kann der Prozess 400 an der Raute 440 fortgesetzt werden, was die Feststellung einschließen kann, ob der indirekte Knoten irgendwelche vorhandenen indirekten Unterknoten hat. Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 feststellen, dass der Knotenpuffer 340 des Wurzelknotens 211 bis zu einem vordefinierten Füllstand gefüllt wurde, und als Reaktion darauf feststellen, ob der Wurzelknoten 211 unmittelbare untergeordnete Knoten hat (d. h. alle untergeordneten Knoten, die eine Ebene unter dem Wurzelknoten 211 liegen). Beachten Sie, dass, wie in gezeigt, die unmittelbaren untergeordneten Knoten des Wurzelknotens 211 indirekte Knoten und keine Blattknoten sind.
-
Wenn in Block 440 festgestellt wird, dass der indirekte Knoten keine bestehenden untergeordneten indirekten Knoten hat, kann der Prozess 400 in Block 450 fortgesetzt werden, der das Bestimmen einer Puffergröße für untergeordnete indirekte Knoten basierend auf einem Ebenenverhältnis beinhalten kann. Block 460 kann die Bestimmung einer Bloom-Filtergröße für untergeordnete indirekte Knoten beinhalten. Zum Beispiel, Bezug nehmend auf , kann der Speicher-Controller 110 feststellen, dass der Wurzelknoten 211 keine untergeordneten Knoten hat, und kann als Reaktion darauf ein Ebenenverhältnis verwenden, um eine Puffergröße für untergeordnete Knoten des Wurzelknotens 211 zu bestimmen. In einigen Beispielen kann das Ebenenverhältnis ein berechnetes Verhältnis zwischen den Gesamtpuffergrößen in zwei benachbarten Ebenen des Schlüssel-Wert-Index 200 sein. Daher können in solchen Beispielen die Gesamtpuffergrößen der indirekten Knoten 221-224 von der Größe des Knotenpuffers des Wurzelknotens 211 abweichen. Außerdem kann der Knotenpuffer jedes indirekten Knotens 221-224 anders sein (z. B. kleiner oder größer) als der Knotenpuffer des Wurzelknotens 211. Ferner kann der Speicher-Controller 110 eine Bloom-Filtergröße für untergeordnete Knoten des Wurzelknotens 211 bestimmen. In einigen Beispielen kann die Bloom-Filtergröße auf der Grundlage von Falsch-Positiv-Verhältnissen bestimmt werden, die mit verschiedenen Ebenen des Schlüssel-Wert-Index 200 verbunden sind.
-
Block 470 kann die Initialisierung eines Satzes untergeordneter Knoten unter Verwendung der ermittelten Puffergröße und Bloom-Filtergröße umfassen. Beispielsweise, unter Bezugnahme auf , kann der Speicher-Controller 110 indirekte Knoten 221-224 als unmittelbare Kinder des Wurzelknotens 211 initialisieren. Ferner kann jeder der untergeordneten Knoten 221-224 einen Knotenpuffer 340 mit einer bestimmten Puffergröße (bestimmt in Block 450) und einen Bloom-Filter 330 mit einer bestimmten Bloom-Filtergröße (bestimmt in Block 460) enthalten.
-
Nach Block 470 oder wenn in Block 440 festgestellt wird, dass der indirekte Knoten vorhandene untergeordnete Knoten hat, kann der Prozess 400 in Block 480 fortgesetzt werden, was die Übertragung aller Schlüssel-Wert-Paare vom Knotenpuffer des indirekten Knotens zu den Knotenpuffern der untergeordneten Knoten (initialisiert in Block 470) beinhalten kann. Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 alle Schlüssel-Wert-Paare vom Knotenpuffer des Wurzelknotens 211 zu den Knotenpuffern der untergeordneten Knoten 221-224 übertragen. In einigen Beispielen wird jedes der übertragenen Schlüssel-Wert-Paare auf einen der untergeordneten Knoten 221-224 basierend auf verschiedenen Schlüsselbereichen verteilt, die den untergeordneten Knoten 221-224 zugeordnet sind.
-
Block 490 kann das Setzen der Bloom-Filter der untergeordneten Knoten beinhalten, um die übertragenen Schlüssel-Wert-Paare anzuzeigen. Beispielsweise kann der Speicher-Controller 110 den Bloom-Filter 330 des untergeordneten Knotens 221 unter Bezugnahme auf so einstellen, dass er die Schlüssel-Wert-Paare anzeigt, die vom Stammknoten 211 an den untergeordneten Knoten 221 übertragen wurden. Der Speicher-Controller 110 kann in ähnlicher Weise die Bloom-Filter 330 der übrigen untergeordneten Knoten 222-224 einstellen. Nach Block 490 kann der Prozess 400 zu Block 410 zurückkehren (d. h., um weiterhin Schreibanfragen zum Hinzufügen von Schlüssel-Wert-Paaren zum Index zu empfangen). Beachten Sie, dass der Prozess 400 in ähnlicher Weise für verschiedene indirekte Knoten des Schlüssel-Wert-Index 200 wiederholt werden kann (z. B. für jeden der indirekten Knoten 221-224, 231-234), und auch am selben indirekten Knoten wiederholt werden kann (z. B. für mehrere Verdichtungen).
-
In einigen Beispielen kann der Prozess 400 das Erzeugen untergeordneter indirekter Knoten mit variabler Größe von Knotenpuffern und Bloom-Filtern ermöglichen. Auf diese Weise kann der Prozess 400 eine Abstimmung der Schreibverstärkung in Verbindung mit der Verwendung des Index sowie eine Optimierung der Speichernutzung in Verbindung mit Bloom-Filtern ermöglichen. Beachten Sie, dass, wie oben beschrieben, der indirekte Knoten, der das Schlüssel-Wert-Paar in Block 410 speichert, mehr als eine Ebene über allen Blattknoten liegt. Anders ausgedrückt: Im Fall eines indirekten Knotens, der unmittelbare Kinder hat, die Blattknoten sind, werden die Aktionen der Blöcke 450-490 (z. B. das Bestimmen einer Knotenpuffergröße, das Bestimmen eines Bloom-Filters, das Initialisieren eines Knotenpuffers und eines Bloom-Filters usw.) nicht für die untergeordneten Blattknoten ausgeführt.
-
5. Lesevorgang mit Bloom-Filter
-
zeigt einen Beispielprozess 500 gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 500 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 500 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Verfahrens 500 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 510 kann den Empfang einer Leseanforderung für ein Schlüssel-Wert-Paar an einem indirekten Knoten eines Schlüssel-Wert-Index umfassen. Zum Beispiel, bezogen auf , kann die Abfrage-Engine 160 eine Abfrage 165 empfangen, die einen Schlüssel angibt. Als Reaktion auf die Abfrage 165 kann die Abfrage-Engine 160 nach dem Schlüssel suchen, indem es Knoten des Schlüssel-Wert-Index 145 in einem Top-Down-Muster analysiert oder liest. Dementsprechend kann die Abfrage-Engine 160 die Suche nach dem Schlüssel am Wurzelknoten 211 beginnen (d. h. dem Knoten mit der höchsten Ebene im Schlüssel-Wert-Index 200).
-
Raute 520 kann die Bestimmung beinhalten, ob ein Bloom-Filter des indirekten Knotens anzeigt, dass das Schlüssel-Wert-Paar in einem Knotenpuffer des indirekten Knotens enthalten ist. Beispielsweise unter Bezugnahme auf , kann der Speicher-Controller 110 bestimmen, ob der Bloom-Filter 330 des Wurzelknotens 211 anzeigt, dass der Knotenpuffer 340 des Wurzelknotens 211 das Schlüssel-Wert-Paar enthält.
-
Wenn bei Raute 520 festgestellt wird, dass der Bloom-Filter anzeigt, dass das Schlüssel-Wert-Paar nicht im Knotenpuffer des indirekten Knotens enthalten ist, dann kann der Prozess 500 bei Block 560 fortgesetzt werden (unten beschrieben). Wenn andernfalls bei Raute 520 festgestellt wird, dass der Bloom-Filter anzeigt, dass das Schlüssel-Wert-Paar im Knotenpuffer des indirekten Knotens enthalten ist, kann der Prozess 500 bei Block 530 fortfahren, was die Verwendung von Fence-Zeigern zur Identifizierung eines Puffer-Blocks (d. h. eines Teils eines Knotenpuffers) des indirekten Knotens beinhalten kann.
-
Raute 540 kann die Bestimmung beinhalten, ob das Schlüssel-Wert-Paar in dem identifizierten Puffer-Bock enthalten ist. Beispielsweise unter Bezugnahme auf , kann die Speicher-Controller 110 die Fence-Zeiger 320 des Wurzelknotens 211 verwenden, um einen Puffer-Block 345 des Wurzelknotens 211 zu identifizieren, der dem Schlüssel-Wert-Paar entspricht (z. B. ein Puffer-Block mit einem Schlüsselbereich, der den gewünschten Schlüssel umfasst). Der Speicher-Controller 110 kann dann den identifizierten Puffer-Block 345 in den Speicher laden und den identifizierten Puffer-Block 345 nach dem Schlüssel-Wert-Paar durchsuchen.
-
Wenn bei Raute 550 festgestellt wird, dass das Schlüssel-Wert-Paar in dem identifizierten Puffer-Block enthalten ist, kann der Prozess 500 bei Block 550 fortgesetzt werden, was das Lesen des Schlüssel-Wert-Paares aus dem identifizierten Puffer-Block beinhalten kann. Zum Beispiel, unter Bezugnahme auf , kann der Speicher-Controller 110 den Wert, der einem bestimmten Schlüssel entspricht, aus dem Knotenpuffer 340 des Wurzelknotens 211 lesen.
-
Wenn jedoch bei Raute 550 festgestellt wird, dass das Schlüssel-Wert-Paar nicht in dem identifizierten Puffer-Block enthalten ist (d. h., der Bloom-Filter hat bei Raute 520 eine „falschpositive“ Anzeige zurückgegeben), dann kann der Prozess 500 bei Block 560 fortgesetzt werden, der die Verwendung von untergeordneten Zeigern des indirekten Knotens beinhalten kann, um einen Unterknoten zu identifizieren (d. h., einen Knoten, der ein unmittelbares Kind des indirekten Knotens ist). Block 570 kann das Durchsuchen des identifizierten untergeordneten Knotens nach dem Schlüssel-Wert-Paar umfassen. Zum Beispiel, unter Bezugnahme auf : Als Reaktion auf die Feststellung, dass der Schlüssel nicht im Knotenpuffer 340 des Wurzelknotens 211 gespeichert ist (d. h. im Falle eines falsch positiven Ergebnisses vom Bloom-Filter 330 des Wurzelknotens 211), kann der Speicher-Controller 110 die untergeordneten Zeiger 310 des Wurzelknotens 211 verwenden, um die indirekten Knoten 221-224 zu identifizieren, die unmittelbare Kinder (d. h. eine Ebene tiefer) des Wurzelknotens 211 sind. Ferner können in diesem Beispiel die untergeordneten Zeiger 310 anzeigen, dass das in der Leseanforderung angegebene Schlüssel-Wert-Paar dem Schlüsselbereich des indirekten Knotens 222 entspricht, und daher kann der Speicher-Controller 110 den indirekten Knoten 222 nach dem Schlüssel-Wert-Paar durchsuchen. Der Speicher-Controller 110 kann das Schlüssel-Wert-Paar lesen, wenn es in dem indirekten Knoten 222 gefunden wird. Nach entweder Block 550 oder Block 570 kann der Prozess 500 abgeschlossen sein.
-
In einigen Beispielen kann der Prozess 500 einen Bloom-Filter in jedem indirekten Knoten verwenden, um zu vermeiden, dass ein Puffer-Block des Knotenpuffers in den Speicher geladen wird. Auf diese Weise kann der Prozess 500 die mit dem Lesen von Schlüssel-Wert-Paaren aus einem Index verbundene Leseverstärkung reduzieren. Beachten Sie, dass der Prozess 500 für verschiedene Ebenen eines Knotenbaums wiederholt und/oder in einer Schleife ausgeführt werden kann. Wenn beispielsweise der in Block 560 identifizierte untergeordnete Knoten ein indirekter Knoten ist, kann die Durchführung von Block 570 (d. h. das Durchsuchen des untergeordneten Knotens nach dem Schlüssel-Wert-Paar) die Durchführung einer weiteren Iteration des Prozesses 500 beinhalten, einschließlich der Verwendung eines Bloom-Filters des untergeordneten Knotens, um festzustellen, ob das Schlüssel-Wert-Paar im untergeordneten Knoten enthalten ist, der Verwendung von Fence-Zeigern des untergeordneten Knotens, um einen Puffer-Block des untergeordneten Knotens zu identifizieren, usw.
-
6. Prozess für Updates während der geplanten Verdichtung
-
zeigt einen Beispielprozess 600 gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 600 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 600 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Prozesses 600 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 610 kann das Hinzufügen von Schlüssel-Wert-Paaren zu einem Knotenpuffer eines indirekten Knotens eines Indexes beinhalten. Zum Beispiel, siehe , kann der Speicher-Controller 110 Schlüssel-Wert-Paare zum Knotenpuffer 340 des Wurzelknotens 211 hinzufügen.
-
Block 620 kann als Reaktion auf die Feststellung, dass der Knotenpuffer des indirekten Knotens einen ersten Schwellenwert überschreitet, die Planung einer Verdichtung des indirekten Knotens mit einer ersten Priorität für die Ausführung im Hintergrund umfassen. Beispielsweise, unter Bezugnahme auf die , kann der Speicher-Controller 110 feststellen, dass der Knotenpuffer 340 des Wurzelknotens 211 bis zu einem ersten Schwellenwert gefüllt ist (z. B. 90 % voll, eine bestimmte Anzahl von Schlüssel-Wert-Paaren, eine bestimmte Menge an verwendetem Speicher usw.). Als Reaktion auf diese Feststellung kann der Speicher-Controller 110 eine Verdichtung des Wurzelknotens 211 planen. Die geplante Verdichtung kann mit einer ersten Priorität (z. B. einer relativ niedrigen Priorität) geplant werden, um als Hintergrundprozess ausgeführt zu werden (z. B. ohne Benutzerinteraktion und/oder nur, wenn die Verarbeitungsbandbreite nicht für Aufgaben mit höherer Priorität benötigt wird).
-
Block 630 kann beinhalten, dass, während auf die Ausführung der Verdichtung gewartet wird, weiterhin Schlüssel-Wert-Paare zum Knotenpuffer des indirekten Knotens hinzugefügt werden. Zum Beispiel, siehe , kann der Speicher-Controller 110, während er auf die Ausführung der geplanten Verdichtung wartet, weiterhin Schlüssel-Wert-Paare zum Knotenpuffer 340 des Wurzelknotens 211 hinzufügen. Dementsprechend wird der Knotenpuffer 340 über den ersten Schwellenwert hinaus gefüllt.
-
Block 640 kann als Reaktion auf eine Feststellung, dass der Knotenpuffer des indirekten Knotens zusätzliche(n) Schwellenwert(e) überschreitet, die Erhöhung der Priorität der geplanten Verdichtung beinhalten. Beachten Sie, dass Block 640 mehrere Prioritätserhöhungen enthalten kann, die dem Erreichen mehrerer Schwellenwerte entsprechen. Zum Beispiel, bezogen auf : Während des Wartens auf die Ausführung der geplanten Verdichtung kann der Speicher-Controller 110 feststellen, dass der Knotenpuffer 340 des Wurzelknotens 211 bis zu einem zweiten Schwellenwert gefüllt wurde, der höher ist als der erste Schwellenwert, und als Reaktion darauf kann er die Priorität der geplanten Verdichtung auf eine zweite Priorität erhöhen, die höher ist als die erste Priorität. Anschließend kann der Speicher-Controller 110 feststellen, dass der Knotenpuffer 340 bis zu einem dritten Schwellenwert gefüllt ist, der höher ist als der zweite Schwellenwert, und als Reaktion darauf kann er die Priorität der geplanten Verdichtung auf eine dritte Priorität erhöhen, die höher ist als die zweite Priorität. Der Speicher-Controller 110 kann eine beliebige Anzahl von Prioritätsanpassungen auf der Grundlage des Erreichens entsprechender Schwellenwerte durch den Knotenpuffer 340 durchführen.
-
Block 650 kann die Ausführung der Verdichtung des indirekten Knotens als Hintergrundprozess beinhalten. Beispielsweise, unter Bezugnahme auf , kann der Speicher-Controller 110 eine Verdichtung als Hintergrundprozess basierend auf seiner aktuellen Prioritätsstufe (z. B. erste Prioritätsstufe, zweite Prioritätsstufe usw.) durchführen. In einigen Beispielen kann der Block 650 einige oder alle der oben unter Bezugnahme auf diskutierten Prozesse 400 enthalten. Nach Block 650 kann der Prozess 600 abgeschlossen sein.
-
In einigen Beispielen kann der Prozess 600 die Verdichtung jedes indirekten Knotens als Hintergrundprozess laufen lassen, während zusätzliche Einträge in einen Knotenpuffer des indirekten Knotens zugelassen werden. Auf diese Weise können Aktualisierungen eines Schlüssel-Wert-Indexes fortgesetzt werden, ohne die Verwendung des indirekten Knotens zu unterbrechen.
-
7. Prozess für sequentielle Schreibladungen
-
zeigt einen Beispielprozess 700, gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 700 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 700 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Prozesses 700 im Folgenden unter Bezugnahme auf beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 710 kann das Erkennen einer sequentiellen Ladung von Schlüssel-Wert-Paaren in einen Index umfassen, während er sich in einem ersten Betriebsmodus befindet, wobei der Index indirekte Knoten mit Knotenpuffern enthält. Beispielsweise, unter Bezugnahme auf die , kann der Speicher-Controller 110 ein Schreiben einer sequentiellen Gruppe von Schlüssel-Wert-Paaren in den Schlüssel-Wert-Index 200 erkennen, der in einem ersten Betriebsmodus verwendet wird. Die sequentielle Gruppe kann mehrere Schlüssel-Wert-Paare enthalten, in denen die Schlüssel eine fortlaufende Sequenz bilden (z.B. 001, 002, 0003, usw.). In einigen Beispielen kann der erste Betriebsmodus des Schlüssel-Wert-Index 200 im Allgemeinen einigen oder allen der oben unter Bezugnahme auf diskutierten Prozesse 400 entsprechen. Beispielsweise kann der erste Betriebsmodus des Schlüssel-Wert-Index 200 das Speichern von Schlüssel-Wert-Paaren im Knotenpuffer jedes indirekten Knotens und das Übertragen der gespeicherten Schlüssel-Wert-Paare an untergeordnete Knoten als Reaktion auf eine Feststellung, dass der Knotenpuffer einen vordefinierten Schwellenwert erreicht hat, umfassen.
-
Block 720 kann als Reaktion auf die Erkennung der sequenziellen Ladungen den Wechsel des Index in einen zweiten Betriebsmodus beinhalten, wobei der zweite Betriebsmodus die Knotenpuffer in den indirekten Knoten nicht verwendet. Zum Beispiel, bezogen auf die , kann der Speicher-Controller 110 als Reaktion auf das Erkennen des Hinzufügens der sequentiellen Gruppe von Schlüssel-Wert-Paaren den Schlüssel-Wert-Index 200 in einen zweiten Betriebsmodus ändern, der die Knotenpuffer 340 in den indirekten Knoten 300 nicht verwendet. In einigen Beispielen kann der zweite Betriebsmodus des Schlüssel-Wert-Index 200 im Allgemeinen dem Betrieb eines B-Baum-Index entsprechen, bei dem die Schlüsselwert-Zuordnungsdaten nur in den Blattknoten gespeichert werden und die indirekten Knoten nur verwendet werden, um den Blattknoten zu identifizieren, der die Zuordnungsdaten für ein bestimmtes Schlüssel-Wert-Paar speichert.
-
Block 730 kann das Hinzufügen der sequenziellen Ladungen zum Index während der zweiten Betriebsart beinhalten. Zum Beispiel, unter Bezugnahme auf , kann der Speicher-Controller 110 die sequentielle Gruppe zu dem Schlüssel-Wert-Index 200 hinzufügen, während er sich im zweiten Betriebsmodus befindet, der die Knotenpuffer 340 nicht verwendet (z. B. gemäß einer B-Baum-Operation), so dass jedes Schlüssel-Wert-Paar in der sequentiellen Gruppe nur in einem Blattknoten des Index 200 gespeichert wird. In einigen Beispielen kann Block 730 beinhalten, dass alle Schlüssel-Wert-Paare in den Knotenpuffern der indirekten Knoten, die mit der sequentiellen Ladung übereinstimmen oder sich überschneiden, zu dem/den entsprechenden Blattknoten hinuntergespült werden. Nach Block 730 kann der Prozess 700 abgeschlossen sein.
-
In einigen Beispielen kann der Prozess 700 es ermöglichen, dass ein Index vorübergehend geändert wird, um sich während der Verarbeitung eines sequentiellen Ladevorgangs wie ein B-Baum-Index zu verhalten. Dementsprechend kann der Prozess 700 eine verbesserte Effizienz bei sequentiellen Ladungen von Schlüssel-Wert-Paaren in einen Index bieten.
-
8. Verfahren zur Bestimmung des Füllstandverhältnisses
-
zeigt einen Beispielprozess 800 gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 800 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 800 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Prozesses 800 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 810 kann die Bestimmung des verfügbaren Speichers in einem Speichersystem beinhalten. In Bezug auf kann der Speicher-Controller 110 beispielsweise die Größe des Speichers 130 bestimmen, der für die Aktualisierung des Schlüssel-Wert-Index 145 verfügbar ist.
-
Block 820 kann den Empfang eines Hinweises auf ein gewünschtes Niveau der Schreibverstärkung beinhalten. In Bezug auf kann der Speicher-Controller 110 beispielsweise eine Benutzereingabe oder einen Befehl empfangen, der ein Niveau der Schreibverstärkung angibt, das vom Benutzer in Bezug auf die Aktualisierung des Schlüssel-Wert-Indexes 145 gewünscht wird (oder für ihn akzeptabel ist).
-
Block 830 kann die Bestimmung eines Ebenenverhältnisses auf der Grundlage des verfügbaren Speichers und des gewünschten Grads der Schreibverstärkung umfassen. In einigen Beispielen kann das Ebenenverhältnis ein festes Verhältnis zwischen den Gesamtpuffergrößen in zwei benachbarten Ebenen eines Schlüsselwertindexes sein. Nehmen wir beispielsweise an, dass der Wurzelknoten 211 in der ersten Ebene 210 eine Puffergröße von 10 MB hat und dass das Ebenenverhältnis 5 ist, dann beträgt die Gesamtgröße der Knotenpuffer in den Knoten der zweiten Ebene 220 50 MB (d. h., das Verhältnis von 5 = 50 MB/10 MB). Ferner beträgt die Gesamtgröße der Knotenpuffer in den Knoten der dritten Ebene 230 250 MB (d. h. Verhältnis von 5 = 250 MB/50 MB). In einigen Beispielen kann der Speicher-Controller 110 das Ebenenverhältnis anhand der folgenden Gleichung bestimmen:
-
In der obigen Gleichung ist der Begriff WAF eine Schreibverstärkungsstufe, L ist die Anzahl der Ebenen (d. h. die Tiefe) des Index, r0 ist das Verhältnis der Puffergröße auf Ebene 0 (d. h. am Stammknoten) zur Größe eines einzelnen Stapels von Benutzeraktualisierungen, rx (wobei x größer als 0 und kleiner als L ist) ist das Verhältnis der Gesamtgröße (d. h., Summe) der Knotenpuffer auf Ebene x zur Gesamtgröße der Knotenpuffer auf Ebene x-1, und rL ist das Verhältnis der Gesamtgröße der Blattknoten (auf der niedrigsten Ebene L) zur Gesamtgröße der Knotenpuffer auf Ebene L-1. In einigen Beispielen kann der Schreibverstärkungsfaktor proportional zur Summe der Ebenenverhältnisse aller Ebenen des Indexes sein. Nach Block 830 kann der Prozess 800 abgeschlossen sein. In einigen Beispielen kann ein Schreibverstärkungsgrad basierend auf einer Menge an verfügbarem Speicher bestimmt werden, und das Ebenenverhältnis kann dann unter Verwendung des Schreibverstärkungsgrads bestimmt werden. In anderen Beispielen kann der Schreibverstärkungsgrad als Eingabeparameter empfangen werden (z. B. wie von einem Benutzer oder einer Konfigurationseinstellung angegeben) und zur Bestimmung des Ebenenverhältnisses verwendet werden. In einigen Beispielen können die Ebenenverhältnisse von verschiedenen Ebenen des Indexes unterschiedlich sein. In einigen Implementierungen kann die obige Gleichung verwendet werden, um den dem Index zugeordneten Schreibverstärkungsgrad abzustimmen oder anzupassen, indem das/die Ebenenverhältnis(se) und/oder der für den Index zugewiesene Speicher angepasst werden. Weiterhin kann die obige Gleichung modifiziert oder angepasst werden (z. B. um zusätzliche oder weniger Parameter einzubeziehen), basierend auf der Systemkonfiguration. Andere Variationen und/oder Kombinationen sind möglich.
-
9. Verfahren zur Bestimmung von Bloom-Filtergrößen
-
zeigt einen Beispielprozess 900 gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 900 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 900 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Prozesses 900 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 910 kann die Bestimmung des verfügbaren Speichers in einem Speichersystem beinhalten. In Bezug auf kann der Speicher-Controller 110 beispielsweise die Größe des Speichers 130 bestimmen, der für die Verwendung des Schlüssel-Wert-Index 145 verfügbar ist.
-
Block 920 kann den Empfang eines Hinweises auf ein Falsch-Positiv-Verhältnis für eine bestimmte Ebene eines Schlüsselwertindexes beinhalten. In Bezug auf kann der Speicher-Controller 110 beispielsweise eine Benutzereingabe oder einen Befehl empfangen, der ein Falsch-Positiv-Verhältnis (z. B. 2 %, 5 % usw.) angibt, das für den Benutzer in Bezug auf das Lesen des Schlüssel-Wert-Indexes 145 akzeptabel ist. In einigen Beispielen kann die empfangene Angabe die Falsch-Positiv-Quote(n) spezifizieren, die für bestimmte Ebenen der indirekten Knoten des Schlüsselwertindexes spezifisch sind (z. B. für die in dargestellte Ebene 230).
-
Block 930 kann die Bestimmung von Falsch-Positiv-Verhältnissen für andere Ebenen des Schlüssel-Wert-Index beinhalten. In einigen Implementierungen können die Falsch-Positiv-Verhältnisse eines Indexes so bestimmt werden, dass höhere Ebenen des Indexes relativ kleinere Falsch-Positiv-Verhältnisse aufweisen als niedrigere Ebenen des Indexes. Weiterhin können die Falsch-Positiv-Verhältnisse einer Ebene durch Multiplikation des Falsch-Positiv-Verhältnisses einer anderen Ebene mit einem konstanten Wert berechnet werden. Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 das Falsch-Positiv-Verhältnis F+1 für die zweitniedrigste Ebene der indirekten Knoten (z. B. Ebene 220 in ) bestimmen, indem das Falsch-Positiv-Verhältnis F der niedrigsten Ebene der indirekten Knoten (z. B. Ebene 230 in ) mit einem konstanten Wert V (z. B. 0,5) multipliziert wird. Ferner kann der Speicher-Controller 110 das Falsch-Positiv-Verhältnis F+2 für die drittniedrigste Ebene der indirekten Knoten (z. B. Ebene 210 in ) bestimmen, indem er sie das Falsch-Positiv-Verhältnis F+1 der zweitniedrigsten Ebene der indirekten Knoten (z. B. Ebene 220 in ) mit dem konstanten Wert V multipliziert.
-
Block 940 kann das Bestimmen von Bloom-Filter-Größen für mehrere Ebenen eines Schlüssel-Wert-Index basierend auf dem verfügbaren Speicher und den Falsch-Positiv-Verhältnissen dieser Ebenen beinhalten. In einigen Implementierungen kann die Größe jedes Bloom-Filters (z. B. die Anzahl der im Bloom-Filter verwendeten Bits) im umgekehrten Verhältnis zum Falsch-Positiv-Verhältnis der zugehörigen Ebene im Index zunehmen. Beispielsweise können die Bloom-Filter-Größen gemäß einer vordefinierten Funktion basierend auf dem Falsch-Positiv-Verhältnis der zugehörigen Ebene variieren (z. B. kann die Bloom-Filter-Größe umgekehrt proportional zum natürlichen Logarithmus der Falsch-Positiv-Rate dieses Bloom-Filters sein). Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 den verfügbaren Speicher unter den verschiedenen Bloom-Filtern im Schlüssel-Wert-Index entsprechend den Falsch-Positiv-Raten der einzelnen Knotenebenen (bestimmt in Block 930) zuordnen. In diesem Beispiel kann festgestellt werden, dass die höheren Ebenen des Index relativ kleinere Falsch-Positiv-Verhältnisse aufweisen, und daher wird dem Bloom-Filter in jedem einzelnen internen Knoten auf einer höheren Ebene eine größere Menge an Speicher pro Schlüssel-Wert-Paar (z. B. Anzahl von Bits) zugewiesen als dem Bloom-Filter in jedem einzelnen internen Knoten auf einer niedrigeren Ebene. Nach Block 940 kann der Prozess 900 abgeschlossen sein.
-
In einigen Implementierungen kann die Bestimmung der Bloom-Filtergrößen unter Verwendung der folgenden Gleichung durchgeführt werden:
-
In der obigen Gleichung ist der TermMBF der Speicherbedarf der Bloom-Filter, e ist die Falsch-Positiv-Wahrscheinlichkeit, C ist die Anzahl der Schlüssel-Wert-Paare, die im Schlüssel-Wert-Index gespeichert werden können, und ri sind die Ebenenverhältnisse der entsprechenden Ebene i (oben mit Bezug auf die Gleichung für den Schreibverstärkungsgrad beschrieben. In einigen Beispielen kann der für die Bloom-Filter benötigte Speicher umgekehrt proportional zum Logarithmus des Falsch-Positiv-Verhältnisses sein und kann proportional zur Kapazität des Index sein. Weiterhin kann der für die Bloom-Filter benötigte Speicher umgekehrt proportional zum Ebenenverhältnis sein, so dass bei einer relativ höheren Ebene der Einfluss des Ebenenverhältnisses auf den Speicherbedarf relativ geringer ist. In einigen Beispielen kann das Falsch-Positiv-Verhältnis auf der Grundlage eines akzeptablen Grads der Leseverstärkung bestimmt werden (z. B. durch einen vom Benutzer eingegebenen Parameter). Wenn genügend Speicher verfügbar ist, werden der Knotenpuffer und der Bloom-Filter für einen bestimmten Knoten erstellt, ohne Rücksicht auf andere Knoten in derselben Ebene.
-
10. Verdichtung im Schlüssel-Wert-Index
-
zeigt einen Beispielprozess 1000, gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 1000 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 1000 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Details des Verfahrens 1000 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 1010 kann den Empfang von Schreibanforderungen zum Hinzufügen von Schlüssel-Wert-Paaren zu einem Index umfassen. Beispielsweise kann die Update-Engine 120 die Aktualisierung 105 im Aktualisierungspuffer 135 speichern, und die Merge-Engine 150 kann den Schlüssel-Wert-Index 145 mit den im Aktualisierungspuffer 135 gespeicherten Schlüssel-Wert-Paaren aktualisieren.
-
Block 1020 kann das Speichern der Schlüssel-Wert-Paare in einem Knotenpuffer eines indirekten Knotens des Index umfassen. Beispielsweise kann der Speicher-Controller 110, wie in den , das empfangene Schlüssel-Wert-Paar im Knotenpuffer 340 des Wurzelknotens 211 speichern.
-
Block 1030 kann die Bestimmung beinhalten, ob der Knotenpuffer des indirekten Knotens einen Schwellenwert überschreitet. Block 1040 kann als Reaktion auf die Feststellung, dass der Knotenpuffer des indirekten Knotens den Schwellenwert überschreitet, die Übertragung der im Knotenpuffer des indirekten Knotens gespeicherten Schlüssel-Wert-Paare an die Knotenpuffer einer Vielzahl von untergeordneten Knoten umfassen, wobei jeder Knotenpuffer der Vielzahl von untergeordneten Knoten eine andere Größe als der Knotenpuffer des indirekten Knotens hat. Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 alle Schlüssel-Wert-Paare aus dem Knotenpuffer 340 des Wurzelknotens 211 an die Knotenpuffer 340 der untergeordneten Knoten 221-224 übertragen. In einigen Beispielen wird jedes der übertragenen Schlüssel-Wert-Paare auf einen der untergeordneten Knoten 221-224 basierend auf verschiedenen Schlüsselbereichen verteilt, die den untergeordneten Knoten 221-224 zugeordnet sind. Ferner kann in einigen Beispielen der Knotenpuffer 340 jedes der untergeordneten Knoten 221-224 kleiner sein als der Knotenpuffer 340 des Wurzelknotens 211. Nach Block 1030 kann der Prozess 1000 abgeschlossen sein.
-
zeigt ein maschinenlesbares Medium 1100, das Befehle 1110-1130 speichert, in Übereinstimmung mit einigen Implementierungen. Die Anweisungen 1110-1130 können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Das maschinenlesbare Medium 1100 kann ein nicht-transitorisches Speichermedium sein, wie z. B. ein optisches, Halbleiter- oder magnetisches Speichermedium.
-
Die Anweisung 1110 kann ausgeführt werden, um Schreibanforderungen zum Hinzufügen von Schlüssel-Wert-Paaren zu einem Index zu empfangen. Anweisung 1120 kann ausgeführt werden, um die Schlüssel-Wert-Paare in einem Knotenpuffer eines indirekten Knotens des Indexes zu speichern. Anweisung 1130 kann ausgeführt werden, um als Reaktion auf eine Feststellung, dass der Knotenpuffer des indirekten Knotens einen Schwellenwert überschreitet, die im Knotenpuffer des indirekten Knotens gespeicherten Schlüssel-Wert-Paare an Knotenpuffer einer Vielzahl von untergeordneten Knoten zu übertragen, wobei jeder Knotenpuffer der Vielzahl von untergeordneten Knoten eine andere Größe als der Knotenpuffer des indirekten Knotens hat.
-
zeigt ein schematisches Diagramm einer Beispiel-Rechenvorrichtung 1200. In einigen Beispielen kann die Rechenvorrichtung 1200 im Allgemeinen dem Speichersystem 100 (dargestellt in entsprechen. Wie gezeigt, kann die Rechenvorrichtung 1200 einen Hardware-Prozessor 1202 und einen maschinenlesbaren Speicher 1205 mit Befehlen 1210-1230 enthalten. Der maschinenlesbare Speicher 1205 kann ein nicht-übertragbares Medium sein. Die Anweisungen 1210-1230 können durch den Hardware-Prozessor 1202 oder durch eine im Hardware-Prozessor 1202 enthaltene Verarbeitungs-Engine ausgeführt werden.
-
Die Anweisung 1210 kann ausgeführt werden, um Schreibanforderungen zum Hinzufügen von Schlüssel-Wert-Paaren zu einem Index zu empfangen. Die Anweisung 1220 kann ausgeführt werden, um die Schlüssel-Wert-Paare in einem Knotenpuffer eines indirekten Knotens des Index zu speichern. Die Anweisung 1230 kann ausgeführt werden, um als Reaktion auf eine Feststellung, dass der Knotenpuffer des indirekten Knotens einen Schwellenwert überschreitet, die im Knotenpuffer des indirekten Knotens gespeicherten Schlüssel-Wert-Paare an Knotenpuffer einer Vielzahl von untergeordneten Knoten zu übertragen, wobei jeder Knotenpuffer der Vielzahl von untergeordneten Knoten eine andere Größe als der Knotenpuffer des indirekten Knotens hat.
-
11. Bloom-Filter im Schlüssel-Wert-Index
-
zeigt einen Beispielprozess 1300 gemäß einigen Implementierungen. In einigen Beispielen kann der Prozess 1300 unter Verwendung einiger oder aller Speicher-Controller 110 (dargestellt in oder Speicher-Controller 117 (dargestellt in durchgeführt werden. Der Prozess 1300 kann in Hardware oder einer Kombination aus Hardware und Programmierung (z. B. maschinenlesbare Anweisungen, die von einem oder mehreren Prozessoren ausgeführt werden können) implementiert werden. Die maschinenlesbaren Anweisungen können in einem nicht-transitorischen, computerlesbaren Medium gespeichert sein, z. B. in einem optischen, Halbleiter- oder magnetischen Speichergerät. Die maschinenlesbaren Anweisungen können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungsmaschine, mehreren Verarbeitungsmaschinen usw. ausgeführt werden. Zur Veranschaulichung werden Einzelheiten des Verfahrens 1300 im Folgenden unter Bezugnahme auf die beschrieben, die Beispiele in Übereinstimmung mit einigen Implementierungen zeigen. Es sind jedoch auch andere Implementierungen möglich.
-
Block 1310 kann den Empfang einer Leseanforderung für ein Schlüssel-Wert-Paar in einem Index umfassen, wobei der Index eine Vielzahl von indirekten Knoten in einer Vielzahl von Ebenen umfasst, wobei jeder indirekte Knoten des Index einen Knotenpuffer und einen Bloom-Filter umfasst und wobei die Größen der Bloom-Filter über die Ebenen gemäß einer vordefinierten Funktion variieren. Zum Beispiel, bezogen auf die , kann die Abfrage-Engine 160 eine Abfrage 165 empfangen, die einen bestimmten Schlüssel angibt. Als Antwort auf die Abfrage 165 kann die Abfrage-Engine 160 nach dem bestimmten Schlüssel suchen, indem sie die Knoten des Schlüssel-Wert-Index 145 in einem Top-Down-Muster analysiert oder liest. In einigen Beispielen kann jeder indirekte Knoten des Schlüssel-Wert-Index 145 einen Knotenpuffer 340 und einen Bloom-Filter 330 enthalten. Die Größen der Bloom-Filter 330 in verschiedenen Ebenen der indirekten Knoten können auf unterschiedlichen Falsch-Positiv-Verhältnissen basieren, die mit den verschiedenen Ebenen des Index 145 verbunden sind. In einigen Beispielen haben höhere Ebenen des Index 145 relativ kleinere Falsch-Positiv-Verhältnisse als niedrigere Ebenen des Index 145. Weiterhin können in einigen Beispielen die Bloom-Filtergrößen gemäß einer vordefinierten Funktion variieren, die auf dem Falsch-Positiv-Verhältnis der zugehörigen Ebene basiert (z. B. kann die Bloom-Filtergröße umgekehrt proportional zum natürlichen Logarithmus der Falsch-Positiv-Rate dieses Bloom-Filters sein).
-
Block 1320 kann als Reaktion auf die Leseanforderung für das Schlüssel-Wert-Paar beinhalten, zu bestimmen, ob der Bloom-Filter eines indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält. Zum Beispiel, unter Bezugnahme auf , kann die Speicher-Controller 110 feststellen, ob der Bloom-Filter 330 des Wurzelknotens 211 anzeigt, dass der Knotenpuffer 340 des Wurzelknotens 211 das Schlüssel-Wert-Paar enthält.
-
Block 1330 kann als Reaktion auf eine Bestimmung, dass der Bloom-Filter des indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält, das Durchsuchen des Knotenpuffers des indirekten Knotens nach dem Schlüssel-Wert-Paar umfassen. Zum Beispiel, bezogen auf , kann der Speicher-Controller 110 feststellen, dass der Bloom-Filter 330 des Wurzelknotens 211 anzeigt, dass der Knotenpuffer 340 des Wurzelknotens 211 das Schlüssel-Wert-Paar enthält, und kann als Reaktion den Knotenpuffer 340 nach dem Schlüssel-Wert-Paar durchsuchen. Nach Block 1330 kann der Prozess 1300 abgeschlossen sein.
-
zeigt ein maschinenlesbares Medium 1400, das Befehle 1410-1430 speichert, in Übereinstimmung mit einigen Implementierungen. Die Befehle 1410-1430 können von einem einzelnen Prozessor, mehreren Prozessoren, einer einzelnen Verarbeitungs-Engine, mehreren Verarbeitungs-Engines und so weiter ausgeführt werden. Das maschinenlesbare Medium 1400 kann ein nicht-transitorisches Speichermedium sein, wie z. B. ein optisches, Halbleiter- oder magnetisches Speichermedium.
-
Die Anweisung 1410 kann ausgeführt werden, um eine Leseanforderung für ein Schlüssel-Wert-Paar in einem Index zu empfangen, wobei der Index eine Vielzahl von indirekten Knoten in einer Vielzahl von Ebenen enthält, wobei jeder indirekte Knoten des Index einen Knotenpuffer und einen Bloom-Filter umfasst und wobei die Größen der Bloom-Filter über die Ebenen gemäß einer vordefinierten Funktion variieren. Die Anweisung 1420 kann ausgeführt werden, um als Reaktion auf die Leseanforderung für das Schlüssel-Wert-Paar zu bestimmen, ob der Bloom-Filter des indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält. Die Anweisung 1430 kann ausgeführt werden, um als Reaktion auf die Feststellung, dass der Bloom-Filter des indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält, den Knotenpuffer des indirekten Knotens nach dem Schlüssel-Wert-Paar zu durchsuchen.
-
zeigt eine schematische Darstellung einer Beispiel-Rechenvorrichtung 1500. In einigen Beispielen kann die Rechenvorrichtung 1500 im Allgemeinen dem Speichersystem 100 (dargestellt in entsprechen. Wie dargestellt, kann die Rechenvorrichtung 1500 einen Hardware-Prozessor 1502 und einen maschinenlesbaren Speicher 1505 mit Befehlen 1510-1530 enthalten. Der maschinenlesbare Speicher 1505 kann ein nicht-übertragbares Medium sein. Die Anweisungen 1510-1530 können durch den Hardware-Prozessor 1502 oder durch eine im Hardware-Prozessor 1502 enthaltene Verarbeitungs-Engine ausgeführt werden.
-
Die Anweisung 1510 kann ausgeführt werden, um eine Leseanforderung für ein Schlüssel-Wert-Paar in einem Index zu empfangen, wobei der Index eine Vielzahl von indirekten Knoten in einer Vielzahl von Ebenen enthält, wobei jeder indirekte Knoten des Index einen Knotenpuffer und einen Bloom-Filter umfasst und wobei die Größen der Bloom-Filter über die Ebenen gemäß einer vordefinierten Funktion variieren. Die Anweisung 1520 kann ausgeführt werden, um als Reaktion auf die Leseanforderung für das Schlüssel-Wert-Paar zu bestimmen, ob der Bloom-Filter des indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält. Anweisung 1530 kann ausgeführt werden, um als Reaktion auf die Feststellung, dass der Bloom-Filter des indirekten Knotens anzeigt, dass der Knotenpuffer des indirekten Knotens das Schlüssel-Wert-Paar enthält, den Knotenpuffer des indirekten Knotens nach dem Schlüssel-Wert-Paar zu durchsuchen.
-
Beachten Sie, dass, obwohl verschiedene Beispiele zeigen, sind Implementierungen in dieser Hinsicht nicht beschränkt. In Bezug auf wird beispielsweise erwogen, dass das Speichersystem 100 zusätzliche Geräte und/oder Komponenten, weniger Komponenten, andere Komponenten, andere Anordnungen usw. enthalten kann. In einem anderen Beispiel wird erwogen, dass die Update-Engine 120 und die Abfrage-Engine 160 zu einer einzigen Engine oder Einheit kombiniert werden können oder in einer anderen Engine oder Software des Speichersystems 100 enthalten sein können. Andere Kombinationen und/oder Variationen sind ebenfalls möglich.
-
Daten und Anweisungen werden in entsprechenden Speichergeräten gespeichert, die als ein oder mehrere computerlesbare oder maschinenlesbare Speichermedien ausgeführt sind. Zu den Speichermedien gehören verschiedene Formen von nicht transitorischen Speichern, darunter Halbleiterspeicher wie dynamische oder statische Direktzugriffsspeicher (DRAMs oder SRAMs), löschbare und programmierbare Festwertspeicher (EPROMs), elektrisch löschbare und programmierbare Festwertspeicher (EEPROMs) und Flash-Speicher; Magnetplatten wie Fest-, Disketten- und Wechselplatten; andere magnetische Medien einschließlich Bändern; optische Medien wie Compact Disks (CDs) oder digitale Videodisks (DVDs); oder andere Arten von Speichergeräten.
-
Beachten Sie, dass die oben besprochenen Anweisungen auf einem einzigen computerlesbaren oder maschinenlesbaren Speichermedium bereitgestellt werden können oder alternativ auf mehreren computerlesbaren oder maschinenlesbaren Speichermedien, die in einem großen System mit möglicherweise mehreren Knoten verteilt sind. Ein solches computerlesbares oder maschinenlesbares Speichermedium oder solche Speichermedien werden als Teil eines Artikels (oder Herstellungsartikels) betrachtet. Ein Artikel oder Herstellungsgegenstand kann sich auf jede hergestellte Einzelkomponente oder mehrere Komponenten beziehen. Das Speichermedium oder die Speichermedien können sich entweder in der Maschine befinden, in der die maschinenlesbaren Anweisungen ausgeführt werden, oder an einem entfernten Standort, von dem maschinenlesbare Anweisungen über ein Netzwerk zur Ausführung heruntergeladen werden können.
-
In der vorstehenden Beschreibung sind zahlreiche Details aufgeführt, um ein Verständnis des hier offengelegten Gegenstands zu ermöglichen. Es können jedoch auch Implementierungen ohne einige dieser Details durchgeführt werden. Andere Implementierungen können Modifikationen und Variationen von den oben beschriebenen Details enthalten. Es ist beabsichtigt, dass die beigefügten Ansprüche solche Modifikationen und Variationen abdecken.