SQL Server’de hem performans tarafında hem de index düzenleme tarafında dikkat edilmesi konulardan biri Page Split işlemidir. Sayfa bölümlendirme olarak tanımlanan bu işlem canlı sistemlerde bazen performans sorununa neden olabilmektedir. Peki Page Split nedir ? Bilindiği gibi SQL Server’in dosya tabanında Page denen 8KB’lık alanlar mevcuttur ve bunlardan 8 tanesi (8*8K=64K) bir extenti oluşturur. Data ve Index verileri page’lerde tutulur ve okuma/yazma işlemleri extent bazında gerçekleşir. Her page’de kaç satırın bulunacağı satırın uzunluğuna bağlı olarak değişebilir. Eğer uzun bir row gelecek olursa veya mevcut row çok uzun bir veriyle güncellenecek olursa SQL Server değişikliği yapmak için mevcut satırların yerini değiştirebilir eğer değişiklik sayfaya sığmıyorsa SQL Server yeni bir sayfa (data page) oluşturup satırları buraya taşır. Bu şekilde öndeki veya sonraki sayfada öteleme işlemleri yapmak zorunda kalır. Bu işleme page split denilir. Sayfaların ne kadar sıklıkla dolacağı ve bölüneceği Fill Factor denen değerle doğrudan ilişkilidir. Bu değer, sayfaların ne kadarlık kısmının dolu olacağını belirtir. Örneğin fillfactor değerini %80 olarak set ettiğimizde bu sayfanın %20’lik kısmı sonradan eklenecek veriler için boş bırakılacaktır. Eğer okuma amaçlı yani az ekleme/güncelleme yapılacan bir veritabanı üzerinde çalışıyorsak doluluk oranının %100’e yakın tutmamız performans artıracaktır. Çünkü daha az page taranmış olacaktır. Eğer yazma işlemleri yoğun yapılıyorsa bu değer yüksekse Page Split işlemi sık yapılmak zorunda kalabilir. Bu da yazma esnasında sisteme zaman kaybettirecektir. Aynı şekilde verilerin bölümlenmesi daha fazla disk yüzeyine yayılmaya neden olduğundan okuma esnasında da performans sorunu yaşanabilir. Aşağıdaki gibi tbDeneme tablosu oluşturalım.
CREATE TABLE tbDeneme(SatirId int,SatirDeger varchar(6000)) GO INSERT tbDeneme VALUES(1,REPLICATE('A',2000)) INSERT tbDeneme VALUES(2,REPLICATE('B',3000))
Bu tablonun page’lerini görelim.
DBCC IND ( 0, ‘tbDeneme’, 1)
Görüldüğü gibi tabloda 810 (IAM Page) ve 808 (Data Page) olmak üzere 2 sayfadan oluşmakta. Bu sayfa türlerinin en anlama geldiğini Ghost Cleanup Nedir ? makalesinde bulabilirsiniz.
Aktif bir transaction içerisinde 2.kaydı güncelleyelim.
BEGIN TRANSACTION UPDATE tbDeneme SET SatirDeger=REPLICATE('B',1500) WHERE SatirId=2
Bu oturumun SPID’si 57 görünmektedir. Başka bir oturumda (SPID=51) bu tabloyu okumaya çalışalım. İşlem commit edilmediği için güncelleme oturumu okuma oturumunu bloke edecektir. Nitekim sp_lock 51 olarak baktığımızda kilitlemeyi görmüş oluruz.
Görüldüğü gibi 808 nolu Data Page, lock edilmiş durumda. Yeni bir sayfa da oluşturulmamış görünüyor. Çünkü taşmaya neden olacak bir durum olmadı.Yeni bir sayfa oluşturma ihtiyacı olacak şekilde daha uzun bir veri girelim.
BEGIN TRANSACTION --INSERT tbDeneme VALUES(2,REPLICATE('C',5000)) --VEYA UPDATE tbDeneme SET SatirDeger=REPLICATE('A',6000) WHERE SatirId=1 UPDATE tbDeneme SET SatirDeger=REPLICATE('B',6000) WHERE SatirId=2
Bu işlemi 57 nolu oturumda yaptığımız için doğrudan bu oturumdaki kilitleme hakkında bilgi alalım (sp_lock 57).
Görüldüğü gibi hem 808 sayfayı lock edildiği hem de 813 numaralı bir sayfa oluşturulmuş ve o da lock edilmiş. 808 sayfanın lock edilmesinin sebebi verinin ROLLBACK edilme ihtimalidir.
Sonuç olarak bu şekilde sayfa oluşturulması, taşınması gibi işlemler işlem zamanını etkileyebilir.z SQL Server tarafında ne kadar page split yapıldığını SQL Server Access Methods: Page Splits/Sec performans sayacından öğrenebiliriz.