sql >> Databasteknik >  >> RDS >> Mysql

Hur undviker man fragmentering när man använder NHibernate guid.comb primärnyckel i MySQL?

Som observerad av Alberto Ferrari och diskuteras här på StackOverflow , Microsoft SQL Server sorterar GUID genom att jämföra byte i en specifik ordning. As MySQL kommer att sortera en BINARY(16) "rakt framåt", allt vi behöver göra, är att ordna om byte när man läser/skriver till databasen.

NHibernate tillåter oss att definiera anpassade datatyper, som kan användas i mappningar mellan databas och objekt. Jag har implementerat en BinaryGuidType , som kan ordna om byte som produceras av Guid.ToByteArray() enligt hur MSSQL sorterar GUID och ordnar om dem till det format som accepteras av Guid(byte[]) konstruktör.

Byteordningen ser ut så här:

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

Spara en System.Guid till en BINARY(16) går så här:

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);

Läser tillbaka byten till en System.Guid går så här:

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];
}

Fullständig källkod för BinaryGuidType här.

Det här verkar fungera bra. Genom att skapa och bevara 10 000 nya objekt i en tabell, lagras de helt sekventiellt, utan tecken på indexfragmentering.




  1. Beställ varcharsträng som numerisk

  2. Utländska nycklar, blockering och uppdateringskonflikter

  3. ansluta till MySQL från kommandoraden

  4. Mysql:Resultatordningen med välj <fältnamn> från skiljer sig från ordningen för resultat med välj * från