sql >> Databáze >  >> RDS >> Mysql

Jak se vyhnout fragmentaci při použití primárního klíče NHibernate guid.comb v MySQL?

Jako pozoroval Alberto Ferrari a diskutované zde na StackOverflow Microsoft SQL Server třídí GUID porovnáním bajtů v určitém pořadí. Protože MySQL bude třídit BINARY(16) „přímo dopředu“, vše, co musíme udělat, je změnit pořadí bajtů při čtení/zápisu do databáze.

NHibernate nám umožňuje definovat vlastní datové typy, které lze použít při mapování mezi databází a objekty. Implementoval jsem BinaryGuidType , schopný změnit pořadí bajtů vytvořených Guid.ToByteArray() podle toho, jak MSSQL třídí GUID a přeskupuje je zpět do formátu akceptovaného Guid(byte[]) konstruktor.

Pořadí bajtů vypadá takto:

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

Ukládání System.Guid na BINARY(16) vypadá takto:

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

Čtení bajtů zpět do System.Guid vypadá takto:

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

Úplný zdrojový kód pro BinaryGuidType zde.

Zdá se, že to funguje dobře. Vytvořením a uložením 10 000 nových objektů do tabulky se ukládají zcela sekvenčně, bez známek fragmentace indexu.




  1. Rychlý příspěvek o SQLite UPSERT a nové klauzuli RETURNING.

  2. Jaký typ sloupce používá SQLAlchemy pro text na MySQL?

  3. Omezte počet znaků ve sloupci dotazu mysql

  4. Nejednoznačný sloupec v příkazu INNER JOIN