3 Ocak 2017 Salı

Yanlış veritipi kullanımının maliyeti

Buruk girdiğimiz 2017'nin ilk yazısı...

Bir müşterimde tablolardaki Clustered Indeksler için Int veritipi yerine Uniqueidentifier veritipinin kullanıldığını gördüm. Önce, en iyi pratiklere göre hangi alanın Clustered Indeks olarak tanımlanabileceğini tekrar hatırlayalım:

- Kısa olmalı,
- Eşsiz değerleri barındırmalı
- Sıralı artan değerleri barındırmalı,
- Değeri değişmemeli,

Konuştuğumuz arkadaşım bana bu tasarım kararını edindikleri kaynaklara binaen aldıklarını söyledi. Bu kaynakların neler olduğunu henüz net olarak bilmiyorum; fakat bu fikir benim bildiğim, uyguladığım ve iyi çalıştığını gördüğüm iyi pratiklerin tam tersiydi. Bu nedenle bu fikre katılamadım, bununla birlikte test etmek istedim. Bu test sonuçlarını sizlerle de paylaşıyorum.

Hatırlatmak gerekirse, Int veritipindeki bir alanın diskte kapladığı alan maliyeti 4 bayttır, Uniqueidentifier alanınki ise 16 bayttır, yani 4 kat daha fazla!

Test için AdventureWorks2014 veritabanındaki Person.Person tablosunu kullandım. Bu tabloyu 2 kere kopyaladım. Birinde, aslındaki gibi BusinessIdentifyId alanını Clustered Indeks olarak tanımladım, diğerine ise Rowguid alanını Clustered Indeks olarak tanımladım. Tablolarda bu iki indeksten başka herhangi bir indeks yoktu.

Daha sonra 2 tablodan da aşağıdaki gibi 1000'er adet kayıt sorguladım:

SELECT TOP (1000) * FROM [dbo].[Person];

BusinessIdentityId alanının Clustered Indeks olduğu tablodan 1000 kaydın okunması için 80 Read yapıldı. Rowguid alanının Clustered Indeks olduğu tablodan 1000 kaydın okunması için ise 188 Read yapıldı. 2,35 kat daha fazla!

Daha sonra iki tabloda da hem Lastname ve Firstname'den oluşan, hem de ModifiedDate için ikişer tane Nonclustered Indeks oluşturdum. Bunun akabinde BusinessIdentityId alanının Clustered Indeks olduğu tablodaki toplam indeks boyutu 1,240kb, Rowguid alanının Clustered Indeks olduğu tablodaki toplam indeks boyutu ise 1,760kb oldu, bu da %42 kat daha fazla demek. Bunun nedeni ise, Clustered olan her tablodaki Nonclustered indekslerin Cluster Key'leri içermesidir.

Clustered Indeks olarak belirlenen alanların genelde Primary Key olduğunu ve ilişkili oldukları ikincil tablolarda da aynı alanların olduğunu hatırlarsak, maliyet iki katına çıkıyor. Join işlemlerinin de bu alanlar üstünden yapıldığını hatırlamakta fayda var, bu da ciddi bir maliyet.

Kayıtların Page'lerde daha fazla yer kaplaması, Page'lerin daha az sayıda kayıt tutabileceği anlamına gelir. Bu da daha fazla kayıt okumak için, daha fazla Page'in hem diskte hem de hafızada yer tutması gerektiği anlamına gelir. Bu da kaynak kullanımını verimsiz hale getirir, performans düşüklüğüne neden olur.

Bu örneğe göre eğer verinizi Int bir alanda saklamak varken (tabii ki iş gereksinimleri buna izin verdiği müddetçe) Uniqueidentifier veritipini seçerseniz, disk ve hafıza maliyetlerinizi ortalama 4 kat arttıracaksınız demektir. Tasarım yaparken bunu bilmekte ve maliyet hesabını buna göre yapmakta büyük fayda var.

Sevgiler,
Ekrem Önsoy

Hiç yorum yok: