Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie vermeide ich eine Fragmentierung bei der Verwendung des Primärschlüssels NHibernate guid.comb in MySQL?

Als beobachtet von Alberto Ferrari und hier auf StackOverflow diskutiert , sortiert Microsoft SQL Server GUIDs, indem er die Bytes in einer bestimmten Reihenfolge vergleicht. Da MySQL einen BINARY(16) sortiert "geradeaus", alles, was wir tun müssen, ist, die Bytes beim Lesen/Schreiben in die Datenbank neu zu ordnen.

Mit NHibernate können wir benutzerdefinierte Datentypen definieren, die in Zuordnungen zwischen Datenbank und Objekten verwendet werden können. Ich habe einen BinaryGuidType implementiert , der in der Lage ist, die von Guid.ToByteArray() gemäß der Art und Weise, wie MSSQL GUIDs sortiert und sie wieder in das von akzeptierte Format umordnet Guid(byte[]) Konstruktor.

Die Byte-Reihenfolge sieht folgendermaßen aus:

int[] ByteOrder = new[] { 10,11,12,13,14,15,8,9,6,7,4,5,0,1,2,3 };

Speichern einer System.Guid zu einem BINARY(16) geht so:

var bytes = ((Guid) value).ToByteArray();
var reorderedBytes = new byte[16];

for (var i = 0; i < 16; i++)
{
    reorderedBytes[i] = bytes[ByteOrder[i]];
}

NHibernateUtil.Binary.NullSafeSet(cmd, reorderedBytes, index);

Lesen der Bytes zurück in eine System.Guid geht so:

var bytes = (byte[]) NHibernateUtil.Binary.NullSafeGet(rs, names[0]);
if (bytes == null || bytes.Length == 0) return null;

var reorderedBytes = new byte[16];

for (var i = 0 ; i < 16; i++)
{
    reorderedBytes[ByteOrder[i]] = bytes[i];
}

Vollständiger Quellcode für den BinaryGuidType hier.

Das scheint gut zu funktionieren. Erstellen und persistieren Sie 10.000 neue Objekte in einer Tabelle, sie werden vollständig sequentiell gespeichert, ohne Anzeichen einer Indexfragmentierung.