ulasdb UUID dediğiniz 128 bitlik karakter ifade 36 byte büyüklüğünde. Eğer bu alana clustered index oluşturursanız yani bu alanı PRIMARY KEY yaparsanız index boyutu çok artacak ve kayıt sayısı arttıkça size sorunlar çıkarmaya başlayacaktır.
Sıralı olmayan UUID kullanıldığında kayıt ekleme işlemleri ile geçen süre doğru orantılıdır. Yani normal auto increment unsigned big integer ya da sıralı UUID clustered indexe sahip bir tabloya 1000 kaydı 1 saniyede giriyorsanız sıralı olmayan UUID kullanan tabloya 1000 kaydı girmeniz atıyorum 10 sn sürecektir.
O yüzden UUID kullanımı dikkat edilmesi gereken bir konu.
Bu konuda öneriler şunlardır:
- UUID primary key olarak kullanmayın. Tablonuzda klasik id kalsın, UUID'yi non-clustered yani ikincil index olarak kullanın. Kendi iç, internal işlerinizde id'yi; dış, public işlerde UUID kullanın. UUID genellikle id'yi gizlemek için kullanılır, sizin de o amaçla kullandığınızı düşünüyorum.
- Performans için sıralı UUID kullanmanız gerekiyor. Evet, farklı farklı (5 adet) UUID tipleri vardır. Bunların ne olduklarını araştırıp öğrenmek iyi olur. Laravel'de
Str::orderedUuid() ile kolayca sıralı UUID oluşturabilirsiniz.
- UUID için kullandığınız alan VARCHAR(36) değil BINARY(16) olmalı ve UUID'yi byte olarak saklamalısınız. Bu, indeksin kapladığı yeri büyük oranda azaltacak ve ileride oluşacak performans problemlerinin de önüne geçecektir. Elbette BINARY(16) alana kayıt yazarken önce BINARY formatına çevirmeniz lazım, ekrana yazarken de tekrar karakter ifadeye dönüştürmeniz lazım. Bununla ilgili MySQL'deki HEX ve UNHEX yöntemlerini, PHP'de hex2bin, bin2hex yöntemlerini araştırabilirsiniz. Laravel'de de
Str::orderedUuid()->getBytes() ile byte çevirme, Uuid::fromBytes($bin) ile binaryden dönüştürme yapabilirsiniz. MySQL 8+ kullanıyorsanız UUID_TO_BIN ve BIN_TO_UUID yöntemleri mevcut.
- Eşleştirmeleri
WHERE uuid = binary_olan_uuid şeklinde yapmanız lazım. WHERE uuidyi_stringe_ceviren_yontem(uuid) = "5c9a9d27-dadd-4ef0-8c9b-6c32fd6b672f" şeklinde yaparsanız indeksten faydalanamazsınız. Mesela MySQL 8 kullanıyorsanız WHERE uuid = BIN_TO_UUID('5c9a9d27-dadd-4ef0-8c9b-6c32fd6b672f') şeklinde olmalı, WHERE BIN_TO_UUID(uuid) ='5c9a9d27-dadd-4ef0-8c9b-6c32fd6b672f' şeklinde olmamalı.
MySQL 8'deki UUID_TO_BIN ve BIN_TO_UUID yöntemlerinin MySQL <8 polyfill fonksiyonları da şu şekilde:
DELIMITER //
CREATE FUNCTION BIN_TO_UUID(bin BINARY(16))
RETURNS CHAR(36) DETERMINISTIC
BEGIN
DECLARE hex CHAR(32);
SET hex = HEX(bin);
RETURN LOWER(CONCAT(LEFT(hex, 8), '-', MID(hex, 9, 4), '-', MID(hex, 13, 4), '-', MID(hex, 17, 4), '-', RIGHT(hex, 12)));
END; //
DELIMITER ;
DELIMITER //
CREATE FUNCTION UUID_TO_BIN(uuid CHAR(36))
RETURNS BINARY(16) DETERMINISTIC
RETURN UNHEX(CONCAT(REPLACE(uuid, '-', ''))); //
DELIMITER ;
Bunları bir migrasyon ile oluşturmak isteyeceksinizdir. Onu da migrasyon içinde şöyle yapabilirsiniz:
up
DB::statement('
CREATE FUNCTION BIN_TO_UUID(bin BINARY(16))
RETURNS CHAR(36) DETERMINISTIC
BEGIN
DECLARE hex CHAR(32);
SET hex = HEX(bin);
RETURN LOWER(CONCAT(LEFT(hex, 8), '-', MID(hex, 9, 4), '-', MID(hex, 13, 4), '-', MID(hex, 17, 4), '-', RIGHT(hex, 12)));
END
');
down
DB::statement('DROP FUNCTION IF EXISTS BIN_TO_UUID');