Wir erwägen, UUID-Werte als Primärschlüssel für unsere MySQL-Datenbank zu verwenden. Die eingefügten Daten werden von Dutzenden, Hunderten oder sogar Tausenden von Remotecomputern generiert und mit einer Rate von 100-40.000 Einfügungen pro Sekunde eingefügt. Wir werden niemals Aktualisierungen vornehmen.
Die Datenbank selbst erreicht normalerweise etwa 50 Millionen Datensätze, bevor wir mit dem Auslesen von Daten beginnen. Es handelt sich also nicht um eine massive Datenbank, sondern auch nicht um eine winzige. Wir planen auch, auf InnoDB zu laufen, obwohl wir offen dafür sind, dies zu ändern, wenn es eine bessere Engine für das gibt, was wir tun.
Wir waren bereit, mit Javas Typ 4-UUID zu arbeiten, haben aber beim Testen ein seltsames Verhalten festgestellt. Zum einen speichern wir als varchar (36) und mir ist jetzt klar, dass wir besser mit binär (16) umgehen können - obwohl ich nicht sicher bin, wie viel besser es uns geht.
Die größere Frage ist: Wie stark vermasseln diese zufälligen Daten den Index, wenn wir 50 Millionen Datensätze haben? Wären wir besser dran, wenn wir zum Beispiel eine UUID vom Typ 1 verwenden würden, bei der die Bits ganz links mit einem Zeitstempel versehen wären? Oder sollten wir UUIDs komplett weglassen und Auto_Increment-Primärschlüssel in Betracht ziehen?
Ich suche nach allgemeinen Gedanken / Tipps zur Leistung verschiedener Arten von UUIDs, wenn diese als Index / Primärschlüssel in MySQL gespeichert sind. Vielen Dank!
Antworten:
Eine UUID ist eine universell eindeutige ID. Es ist der universelle Teil, den Sie hier berücksichtigen sollten.
Benötigen Sie wirklich die IDs, um universell eindeutig zu sein? In diesem Fall sind UUIDs möglicherweise Ihre einzige Wahl.
Ich würde dringend empfehlen, UUIDs, wenn Sie sie verwenden, als Zahl und nicht als Zeichenfolge zu speichern. Wenn Sie über 50 Millionen Datensätze verfügen, verbessert die Einsparung von Speicherplatz Ihre Leistung (obwohl ich nicht sagen kann, um wie viel).
Wenn Ihre IDs nicht universell eindeutig sein müssen, können Sie meiner Meinung nach nicht viel besser als nur auto_increment, was garantiert, dass IDs innerhalb einer Tabelle eindeutig sind (da der Wert jedes Mal erhöht wird).
quelle
binary
Format. Ich meine als 128-Bit-Zahl und nicht als 288-Bit-Zeichenfolge. Zum Beispiel ist das Wort "Hallo" in ASCII68 65 6C 6C 6F
die Nummer 448,378,203,247. Das Speichern der Zeichenfolge '68656C6C6F' erfordert 10 Byte. Die Nummer 448,378,203,247 erfordert nur 5. Alles in allem können Sie nicht viel besser machen alsauto_increment
Bei meiner Arbeit verwenden wir UUID als PKs. Was ich Ihnen aus Erfahrung sagen kann, ist, SIE NICHT als PKs zu verwenden (SQL Server übrigens).
Es ist eines dieser Dinge, dass es in Ordnung ist, wenn Sie weniger als 1000 Datensätze haben, aber wenn Sie Millionen haben, ist es das Schlimmste, was Sie tun können. Warum? Da die UUID nicht sequentiell sind, muss MSSQL jedes Mal, wenn ein neuer Datensatz eingefügt wird, auf die richtige Seite schauen, um den Datensatz einzufügen, und dann den Datensatz einfügen. Die wirklich hässliche Konsequenz daraus ist, dass die Seiten alle unterschiedlich groß und fragmentiert sind. Jetzt müssen wir regelmäßig eine De-Fragmentierung durchführen.
Wenn Sie eine automatische Inkrementierung verwenden, wechselt MSSQL immer zur letzten Seite, und Sie erhalten (theoretisch) gleich große Seiten, sodass die Leistung bei der Auswahl dieser Datensätze viel besser ist (auch, weil die INSERTs die Tabelle / Seite nicht blockieren so lange).
Der große Vorteil der Verwendung von UUID als PKs besteht jedoch darin, dass bei Zusammenführung von DB-Clustern beim Zusammenführen keine Konflikte auftreten.
Ich würde das folgende Modell empfehlen: 1. PK INT-Identität 2. Zusätzliche Spalte, die automatisch als UUID generiert wird.
Auf diese Weise ist der Zusammenführungsprozess möglich (UUID wäre Ihr REAL-Schlüssel, während die PK nur vorübergehend ist und Ihnen eine gute Leistung bietet).
HINWEIS: Die beste Lösung ist die Verwendung von NEWSEQUENTIALID (wie ich in den Kommentaren sagte), aber für ältere Apps, die nicht viel Zeit für die Umgestaltung haben (und noch schlimmer, nicht alle Einfügungen steuern), ist dies nicht möglich. Aber ab 2017 würde ich sagen, dass die beste Lösung hier NEWSEQUENTIALID ist oder Guid.Comb mit NHibernate macht.
Hoffe das hilft
quelle
Zu berücksichtigen ist, dass Autoincrements einzeln generiert werden und nicht mit einer parallelen Lösung gelöst werden können. Der Kampf um die Verwendung von UUIDs hängt letztendlich davon ab, was Sie erreichen möchten und was Sie möglicherweise opfern.
Zur Aufführung kurz :
Ich empfehle die folgenden zwei Beiträge zu lesen:
Ich rechne zwischen den beiden, sie beantworten Ihre Frage.
quelle
Ich neige dazu, UUID zu vermeiden, nur weil es ein Schmerz ist, sie zu speichern und als Primärschlüssel zu verwenden, aber es gibt Vorteile. Das wichtigste ist, dass sie EINZIGARTIG sind.
Normalerweise löse ich das Problem und vermeide UUID, indem ich Felder mit zwei Schlüsseln verwende.
COLLECTOR = EINZIGARTIG, DER EINER MASCHINE ZUGEWIESEN IST
ID = Vom Sammler gesammelter Datensatz (Feld auto_inc)
Das bietet mir zwei Dinge. Geschwindigkeit der Auto-Inc-Felder und Eindeutigkeit der Daten, die an einem zentralen Ort gespeichert werden, nachdem sie gesammelt und gruppiert wurden. Ich weiß auch beim Durchsuchen der Daten, wo sie gesammelt wurden, was für meine Bedürfnisse oft sehr wichtig ist.
Ich habe viele Fälle beim Umgang mit anderen Datensätzen für Kunden gesehen, in denen sie sich für die Verwendung von UUID entschieden haben, aber dann noch ein Feld haben, in dem die Daten gesammelt wurden, was wirklich eine Verschwendung von Aufwand ist. Es hilft wirklich, einfach zwei (oder mehr, falls erforderlich) Felder als Schlüssel zu verwenden.
Ich habe gerade zu viele Performance-Hits mit UUID gesehen. Sie fühlen sich wie ein Betrüger ...
quelle
Wie wäre es, Schlüsselblöcke einzelnen Servern zuzuweisen, anstatt für jede Einfügung zentral eindeutige Schlüssel zu generieren? Wenn ihnen die Schlüssel ausgehen, können sie einen neuen Block anfordern. Dann lösen Sie das Overhead-Problem, indem Sie für jeden Einsatz eine Verbindung herstellen.
Der Keyserver verwaltet die nächste verfügbare ID
muss
Sie könnten eine komplexere Version entwickeln, bei der ein Server die Anzahl der benötigten Schlüssel anfordern oder nicht verwendete Blöcke an den Schlüsselserver zurückgeben könnte, der dann natürlich eine Karte der verwendeten / nicht verwendeten Blöcke verwalten müsste.
quelle
Ich würde jedem Server auf transaktionale Weise eine numerische ID zuweisen. Dann erhöht jeder eingefügte Datensatz automatisch seinen eigenen Zähler. Die Kombination von ServerID und RecordID ist eindeutig. Das Feld "ServerID" kann indiziert werden, und die zukünftige Auswahlleistung basierend auf der ServerID (falls erforderlich) ist möglicherweise viel besser.
quelle
Die kurze Antwort lautet, dass viele Datenbanken aufgrund eines Konflikts zwischen ihrer Indizierungsmethode und der absichtlichen Entropie der UUIDs in den höherwertigen Bits Leistungsprobleme haben (insbesondere bei hohen INSERT-Volumes). Es gibt mehrere gängige Hacks:
... aber das sind alles Hacks - und wahrscheinlich auch fragile.
Die beste, aber leider langsamste Antwort besteht darin, von Ihrem Anbieter zu verlangen, dass er sein Produkt verbessert, damit er wie jeder andere Typ UUIDs als Primärschlüssel verarbeiten kann. Sie sollten Sie nicht zwingen, Ihren eigenen halbgebackenen Hack zu würfeln, um das Versagen auszugleichen, das zu einem gängigen Anwendungsfall geworden ist und nur weiter wachsen wird.
quelle
Was ist mit einer handgefertigten UID? Geben Sie jedem der Tausenden von Servern eine ID und machen Sie den Primärschlüssel zu einem Kombinationsschlüssel für die automatische Inkrementierung, MachineID ???
quelle
Da der Primärschlüssel dezentral generiert wird, haben Sie ohnehin keine Möglichkeit, ein auto_increment zu verwenden.
Wenn Sie die Identität der Remotecomputer nicht verbergen müssen, verwenden Sie UUIDs vom Typ 1 anstelle von UUIDs. Sie sind einfacher zu generieren und können die Leistung der Datenbank zumindest nicht beeinträchtigen.
Das gleiche gilt für varchar (char, wirklich) vs. binär: Es kann nur helfen. Ist es wirklich wichtig, wie viel Leistung verbessert wird?
quelle