Wenn ein HiLo verwendet wird, was passiert, wenn Sie die Kapazität (Maximum Lo) ändern?

8

Wenn ich anfange, einen HiLo-Generator zu verwenden, um IDs für eine Tabelle zuzuweisen und dann zu entscheiden, die Kapazität zu erhöhen oder zu verringern (dh den maximalen 'lo'-Wert), wird dies Kollisionen mit den bereits zugewiesenen IDs verursachen?

Ich frage mich nur, ob ich eine große rote Fahne um die Nummer legen muss, die sagt "Ändere das niemals!"

Hinweis - nicht NHibernate-spezifisch, ich bin nur neugierig auf den HiLo-Algorithmus im Allgemeinen.

    
Jon M 21.06.2010, 11:16
quelle

4 Antworten

20

HiLo-Algorithmen ordnen im Allgemeinen zwei ganze Zahlen einer Ganzzahl-ID zu. Es garantiert, dass das Zahlenpaar pro Datenbank eindeutig ist. In der Regel besteht der nächste Schritt darin, sicherzustellen, dass ein eindeutiges Zahlenpaar einer eindeutigen Ganzzahl-ID zugeordnet wird.

Eine schöne Erklärung dafür, wie HiLo konzeptionell funktioniert, finden Sie in dieser vorherigen SO-Antwort

Wenn Sie max_lo ändern, wird die Eigenschaft beibehalten, dass Ihr Zahlenpaar eindeutig ist. Wird es jedoch sicherstellen, dass die zugeordnete ID eindeutig und kollisionsfrei ist?

Schauen wir uns die Hibernate-Implementierung von HiLo an. Der Algorithmus, den sie zu verwenden scheinen (aus dem, was ich gesammelt habe) ist: (und ich könnte mich auf eine Technik verlassen)

%Vor%

Wenn also Ihr Low-Block beispielsweise 100 ist, würden Ihre reservierten ID-Blöcke 1-100, 101-200, 201-300, 301-400 ... gehen.

Deine High-Sequenz ist jetzt 3. Was würde passieren, wenn du deine l_size plötzlich auf 10 änderst? Dein nächster Block, dein High wird erhöht, und du erhältst 4*10+1 = 41

Hoppla! Dieser neue Wert fällt definitiv in den "reservierten Block" von 1-100 . Jemand mit einer hohen Folge von 0 würde denken: "Nun, ich habe den Bereich 1-100 nur für mich reserviert, also werde ich einfach einen bei 41 hinlegen, weil ich weiß, dass es sicher ist."

Es besteht definitiv eine sehr, sehr hohe Wahrscheinlichkeit einer Kollision, wenn das l_max verringert.

Was ist mit dem umgekehrten Fall, wenn Sie ihn erhöhen?

Zurück zu unserem Beispiel, heben wir unsere l_size auf 500, drehen den nächsten Schlüssel in 4*500+1 = 2001 und reservieren den Bereich 2001-2501.

Es sieht so aus, als würde in dieser speziellen Implementierung von HiLo eine Kollision vermieden, wenn Ihr l_max erhöht.

Natürlich sollten Sie selbst einige Tests durchführen, um sicherzustellen, dass dies die tatsächliche Implementierung ist oder in der Nähe ist. Ein Weg wäre, l_max auf 100 zu setzen und die ersten paar Schlüssel zu finden, dann auf 500 zu setzen und den nächsten zu finden. Wenn es einen großen Sprung wie hier erwähnt gibt, könntest du sicher sein.

Ich behaupte jedoch keineswegs, dass es empfehlenswert ist, Ihr l_max auf einer bestehenden Datenbank zu erhöhen.

Verwenden Sie Ihr eigenes Ermessen; Der HiLo-Algorithmus ist nicht genau einer, der mit unterschiedlichen l_max-Werten erstellt wurde, und Ihre Ergebnisse können am Ende unvorhersehbar sein, abhängig von Ihrer genauen Implementierung. Vielleicht kann jemand, der Erfahrung mit der Erhöhung ihrer L_max und dem Auffinden von Beschwerden hat, diese Anzahl als korrekt bestätigen.

Fazit: Obwohl die HiLo-Implementierung von Hibernate höchstwahrscheinlich Kollisionen vermeiden wird, wenn l_max erhöht wird, ist dies wahrscheinlich immer noch keine gute Übung. Sie sollten so programmieren, als würde sich l_max im Laufe der Zeit nicht ändern.

Aber wenn Sie Glück haben ...

    
Justin L. 21.06.2010, 12:04
quelle
3

Siehe den Tabellenzuordner für den linearen Chunk - dies ist logisch ein einfacher & amp; korrekte Annäherung an das gleiche Problem.

Was ist der Hi / Lo-Algorithmus?

Durch Zuweisung von Bereichen aus dem Zahlenraum & amp; Anstatt die Logik mit hohen Wörtern oder multiplizierten Zahlen zu verkomplizieren, können Sie direkt sehen, welche Schlüssel generiert werden.

Im Wesentlichen verwendet "Linear Chunk allocator" addition statt Multiplikation . Wenn der NEXT 1000 & amp; Wir haben eine Bereichsgröße von 20 konfiguriert, NEXT wird auf 1020 erweitert, und wir halten die Schlüssel 1000-1019 für die Zuweisung bereit.

Range-sized kann jederzeit ohne Verlust der Integrität angepasst oder neu konfiguriert werden. Es besteht eine direkte Beziehung zwischen dem NEXT-Feld des Zuweisers, den erzeugten Schlüsseln & amp; MAX (ID) in der Tabelle vorhanden.

(Zum Vergleich, "Hi-Lo" verwendet Multiplikation . Wenn der nächste Wert 50 ist und der Multiplikator 20 ist, dann werden Schlüssel um 1000-1019 zugewiesen. Es gibt keine direkte Korrelation zwischen NEXT, generierten Schlüsseln und MAX (ID) in der Tabelle ist es schwierig, NEXT sicher einzustellen, und der Multiplikator kann nicht geändert werden, ohne den aktuellen Zuweisungspunkt zu stören.)

Mit "Linear Chunk" können Sie konfigurieren, wie groß jeder Bereich / Chunk ist - die Größe von 1 entspricht dem traditionellen Tabellen-basierten "Single Allocator" & amp; Hits die Datenbank, um jeden Schlüssel zu generieren, Größe von 10 ist 10x schneller, da es einen Bereich von 10 auf einmal zuweist, Größe von 50 oder 100 ist noch schneller ..

Eine Größe von 65536 erzeugt hässlich aussehende Schlüssel, verschwendet eine große Anzahl von Schlüsseln beim Neustart des Servers und entspricht dem ursprünglichen HI-LO-Algorithmus von Scott Ambler.

Kurz gesagt, Hi-Lo ist ein irrtümlich komplexer & amp; fehlerhafter Ansatz zu dem, was konzeptionell einfach sein sollte - Zuweisung von Bereichen entlang einer Zahlenzeile.

    
Thomas W 08.11.2013 01:00
quelle
2

Ich habe versucht, das Verhalten des HiLo-Algorithmus durch eine einfache halloWrold-ish Hibernate-Anwendung aufzudecken.

Ich habe ein Hibernate-Beispiel mit

versucht %Vor%

Tabelle mit dem Namen "HILO_TABLE" erstellt mit der einzelnen Spalte "TEST_HILO" Anfangs habe ich den Wert der Spalte TEST_HILO auf 8 gesetzt.

%Vor%

Ich habe beobachtet, dass das Muster zum Erstellen einer ID

ist %Vor%

hivalue ist der Spaltenwert in DB (d. h. TEST_HILO aus HILO_TABLE auswählen) lowvalue stammt von config xml (40)

Also in diesem Fall IDs begann von 8 * 40 + 8 = 328

In meinem Hibernate-Beispiel habe ich 200 Zeilen in einer Sitzung hinzugefügt. Daher wurden Zeilen mit den IDs 328 bis 527 erstellt Und in DB wurde hivalue bis 13 inkrementiert. Die Inkrementlogik scheint zu sein: -

%Vor%

= 8 + 200/40 = 8 + 5 = 13

Wenn ich jetzt dasselbe Hibernate-Programm zum Einfügen von Zeilen verwende, sollten die IDs beginnen 13 * 40 + 13 = 533

Wenn das Programm ausgeführt wurde, wurde es bestätigt.

    
Kaushik Lele 08.11.2012 09:23
quelle
1

Nur aus Erfahrung würde ich sagen: Ja, das Verringern wird Kollisionen verursachen. Wenn Sie ein niedrigeres Maximum haben, erhalten Sie niedrigere Zahlen, unabhängig von dem hohen Wert in der Datenbank (der auf die gleiche Weise gehandhabt wird, z. B. mit jeder Sitzungs-Factory-Instanz im Falle von NH).

Es besteht die Möglichkeit, dass eine Zunahme keine Kollisionen verursacht. Aber Sie müssen entweder jemanden fragen oder fragen, der es besser weiß, um sicherzugehen.

    
Stefan Steinegger 21.06.2010 11:41
quelle

Tags und Links