Ich habe kürzlich eine SQL Server-Datenbank geerbt , die Guids speichert, BINARY(16)
anstatt sie UNIQUEIDENTIFIER
zu verwenden. Dies wird für alles ausgeführt, einschließlich der Primärschlüssel.
Sollte ich besorgt sein?
sql-server
migration
uuid
Jonathan Allen
quelle
quelle
Antworten:
Nun, es gibt ein paar Dinge, die ein wenig betreffen.
Erstens: Während es wahr ist, dass a
UNIQUEIDENTIFIER
(dhGuid
) ein 16-Byte-Binärwert ist, ist es auch wahr, dass:INT
können in gespeichert werdenBINARY(4)
,DATETIME
können inBINARY(8)
usw. gespeichert werden), daher # 2 ↴sysname
als Alias fürNVARCHAR(128)
).Die drei Verhaltensunterschiede, die ich finden kann, sind:
Das Vergleichen von
UNIQUEIDENTIFIER
Werten in SQL Server zum Guten oder Schlechten erfolgt nicht auf die gleiche Weise wie das Vergleichen vonBINARY(16)
Werten. Laut der MSDN-Seite zum Vergleichen von GUID- und Uniqueidentifier-Werten beim Vergleichen vonUNIQUEIDENTIFIER
Werten in SQL Server:Obwohl diese Werte nicht häufig sortiert werden, gibt es einen kleinen Unterschied zwischen diesen beiden Typen. Laut der MSDN-Seite für uniqueidentifier :
Da es Unterschiede in der Handhabung von GUID-Werten zwischen SQL Server und .NET gibt (siehe oben auf der Seite "Vergleichen von GUID- und Uniqueidentifier-Werten"), wird das Abrufen dieser Daten aus SQL Server in den Anwendungscode möglicherweise nicht ordnungsgemäß behandelt den App-Code, wenn das SQL Server-Vergleichsverhalten emuliert werden muss. Dieses Verhalten kann durch Konvertieren in a emuliert werden. Wüsste
SqlGuid
ein Entwickler, dass dies möglich ist?Zweitens: basierend auf der folgenden Aussage
Ich würde im Allgemeinen für die Systemleistung besorgt sein, indem ich GUIDs als PKs anstelle von alternativen Schlüsseln zusammen mit einer
INT
oder sogarBIGINT
als PK verwende. Und noch besorgter, wenn diese GUID-PKs die Clustered-Indizes sind.AKTUALISIEREN
Der folgende Kommentar des OP zur Antwort von @ Rob gibt Anlass zu zusätzlicher Besorgnis:
GUIDs können in 2 verschiedenen Binärformaten gespeichert werden . Es könnte also Anlass zur Sorge geben, abhängig von:
Das Problem, bei dem die Binärdarstellung generiert wurde, hat mit der Byte-Reihenfolge der ersten 3 der 4 "Felder" zu tun. Wenn Sie dem obigen Link zum Wikipedia-Artikel folgen, wird in RFC 4122 angegeben, dass für alle 4 Felder die Codierung "Big Endian" verwendet werden soll. Microsoft GUIDs geben jedoch "Native" Endianness an. Nun, die Intel-Architektur ist Little Endian, daher wird die Bytereihenfolge für die ersten drei Felder von Systemen umgekehrt, die dem RFC folgen (sowie von Microsoft-ähnlichen GUIDs, die auf Big Endian-Systemen generiert wurden). Das erste Feld "Daten 1" besteht aus 4 Bytes. In einer Endianness würde es als (hypothetisch) dargestellt werden
0x01020304
. Aber in der anderen Endianness wäre es0x04030201
. Also, wenn die aktuelle Datenbank 'BINARY(16)
Diese binäre Darstellung wurde auf einem System nach dem RFC generiert. Die Konvertierung der aktuell imBINARY(16)
Feld vorhandenen Daten in eineUNIQUEIDENTIFIER
führt zu einer anderen GUID als ursprünglich erstellt. Dies ist kein wirkliches Problem, wenn die Werte die Datenbank nie verlassen haben und immer nur auf Gleichheit und Nicht-Reihenfolge verglichen werden.Die Sorge bei der Bestellung ist einfach, dass sie nach der Konvertierung in nicht in derselben Reihenfolge sind
UNIQUEIDENTIFIER
. Glücklicherweise wurde, wenn das ursprüngliche System wirklich MySQL war, die Bestellung nie in der Binärdarstellung ausgeführt, da MySQL nur eine Zeichenfolgendarstellung von UUID hat .Das Problem mit den Zeichenfolgenwerten, die außerhalb der Datenbank verwendet werden, ist erneut schwerwiegender, wenn die Binärdarstellung außerhalb von Windows / SQL Server generiert wurde. Da die Bytereihenfolge möglicherweise unterschiedlich ist, würde dieselbe GUID in Zeichenfolgenform zu zwei verschiedenen Binärdarstellungen führen, je nachdem, wo diese Konvertierung stattgefunden hat. Wenn App-Code oder Kunden eine GUID in Zeichenfolgenform erhalten,
ABC
die aus einer Binärform von stammt,123
und die Binärdarstellung auf einem System nach dem RFC generiert wurde, wird dieselbe Binärdarstellung (dh123
)DEF
bei der Konvertierung in eine Zeichenfolgenform von übersetzt aUNIQUEIDENTIFIER
. Ebenso würde die ursprüngliche Zeichenfolgenform vonABC
in eine binäre Form von456
konvertiert, wenn sie in a konvertiert wirdUNIQUEIDENTIFIER
.Wenn die GUIDs die Datenbank also nie verlassen haben, gibt es außerhalb der Bestellung nicht viel zu befürchten. Oder wenn der Import von MySQL durch Konvertieren der Zeichenfolgenform (dh
FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40
) durchgeführt wurde, ist dies möglicherweise in Ordnung. Wenn diese GUIDs an Kunden oder im App-Code vergeben wurden, können Sie testen, wie sie konvertieren, indem Sie eine abrufen und über konvertierenSELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');
und prüfen, ob Sie den erwarteten Datensatz finden. Wenn Sie keine Datensätze finden können, müssen Sie die Felder möglicherweise so belassenBINARY(16)
.Höchstwahrscheinlich wird es kein Problem geben, aber ich erwähne dies, weil es unter den richtigen Bedingungen ein Problem geben könnte.
Und wie werden neue GUIDs überhaupt eingefügt? Im App-Code generiert?
UPDATE 2
Wenn die vorherige Erläuterung des potenziellen Problems beim Importieren von GUID-Binärdarstellungen, die auf einem anderen System generiert wurden, ein wenig (oder viel) verwirrend war, wird hoffentlich Folgendes deutlicher:
In der oben gezeigten Ausgabe stammen die Werte "String" und "Binary" von derselben GUID. Der Wert unter der Zeile "Binary" entspricht dem Wert der Zeile "Binary", ist jedoch im selben Stil wie die Zeile "String" formatiert (dh "0x" wurde entfernt und die vier Bindestriche hinzugefügt). Beim Vergleich des ersten und dritten Werts sind sie nicht genau gleich, aber sehr ähnlich: Die beiden Abschnitte ganz rechts sind identisch, die drei Abschnitte ganz links jedoch nicht. Wenn Sie jedoch genau hinschauen, können Sie feststellen, dass es sich in jedem der drei Abschnitte um dieselben Bytes handelt, nur in einer anderen Reihenfolge. Es ist möglicherweise einfacher zu erkennen, ob ich nur die ersten drei Abschnitte zeige und die Bytes nummeriere, damit leichter zu erkennen ist, wie sich ihre Reihenfolge zwischen den beiden Darstellungen unterscheidet:
Zeichenfolge = 1 5F 2 ED 3 23 4 BE - 5 E5 6 2C - 7 40 8 EE
Binär = 4 BE 3 23 2 ED 1 5F - 6 2C 5 E5 - 8 EE 7 40 (in Windows / SQL Server)
Innerhalb jeder Gruppierung ist die Reihenfolge der Bytes umgekehrt, jedoch nur innerhalb von Windows und auch von SQL Server. Auf einem System, das den RFC einhält, würde die Binärdarstellung jedoch die Sting-Darstellung spiegeln, da die Bytereihenfolge nicht umgekehrt würde.
Wie wurden die Daten von MySQL in SQL Server gebracht? Hier sind einige Möglichkeiten:
Kehrt zurück:
Unter der Annahme, dass es sich um eine direkte Binär-zu-Binär-Konvertierung handelt (dh obige Konvertierung Nr. 2), würde die resultierende GUID bei einer Konvertierung in eine tatsächliche wie
UNIQUEIDENTIFIER
folgt lauten:Kehrt zurück:
Was falsch ist. Und das lässt uns drei Fragen offen:
quelle
Sie können immer besorgt sein. ;)
Das System wurde möglicherweise von einem anderen System migriert, das die eindeutige Kennung nicht unterstützt. Gibt es noch andere Kompromisse, die Sie nicht kennen?
Dem Designer ist der Typ der eindeutigen Kennung möglicherweise nicht bekannt. Welche anderen Dinge wussten sie nicht?
Technisch gesehen sollte es kein großes Problem sein.
quelle