MSSQL Server’da PAGEIOLATCH Bekleme Tipi

SQL Server performans analizinde PAGEIOLATCH, en sık karşılaşılan ve genellikle “Disk yavaş mı?” sorusunu akıllara getiren bekleme tipidir. Ancak her zaman suçlu disk olmayabilir.

Bir sorgu çalıştığında, ihtiyacı olan veri sayfası (page) bellekte (Buffer Pool) yoksa, SQL Server bu sayfayı diskten okuyup belleğe getirmek zorundadır.

PAGEIOLATCH, SQL Server’ın bir veri sayfasını diskten belleğe çekene kadar geçen süreyi temsil eder.

  • PAGE: Veri sayfası.
  • IO: Girdi/Çıktı (Disk işlemi).
  • LATCH: Sayfa belleğe yerleşene kadar üzerine konulan fiziksel kilit.

Görülen Tipleri:

PAGEIOLATCH_EX

Bu bekleme tipinin görülmesine neden olan temel işlemler şunlardır:

1. Veritabanına Yeni Veri Yazma (Data Insertion)

En yaygın sebep budur. Eğer SQL Server yeni veriler eklemek için diskten yeni bir “boş sayfa” çekiyorsa veya mevcut bir sayfayı güncelleyip (Update) belleğe yazmaya çalışıyorsa bu bekleme oluşur.

  • Bulk Insert İşlemleri: Milyonlarca satırı aynı anda içeri aktarmaya çalıştığınızda.
  • Yoğun INSERT/UPDATE trafiği: Disk yazma hızının (I/O) bellek hızına yetişememesi.

2. Index Bakımı ve Yeniden Oluşturma (Index Rebuild)

Bir index’i REBUILD veya REORGANIZE ettiğinizde, SQL Server devasa miktarda sayfayı diskten okur, bellekte yeniden düzenler ve tekrar diskle eşitleyerek yazar. Bu süreçte sayfalar üzerinde “Exclusive” (Özel) kilit tutulur.

  • Eğer disk alt yapınız bu yoğun yazma trafiğini karşılayamazsa PAGEIOLATCH_EX tavan yapar.

3. Sayfa Bölünmeleri (Page Splits)

Eğer bir tabloya veri eklenirken mevcut sayfa dolmuşsa ve araya veri girmesi gerekiyorsa (özellikle rastgele GUID kullanımı gibi durumlarda), SQL Server yeni bir sayfa tahsis eder ve verinin bir kısmını oraya taşır.

  • Bu “taşıma ve yeni sayfa oluşturma” işlemi fiziksel bir I/O gerektirdiğinden bu bekleme tipini tetikler.

4. TempDB Üzerindeki Yoğun Yazma

Geçici tablolar (#temp) veya karmaşık sorguların oluşturduğu “Worktables/Workfiles” (Sort veya Hash işlemleri belleğe sığmadığında diske taşması) diskte sürekli yeni alan yazılmasını gerektirir. TempDB’nin bulunduğu disk yavaşsa bu hata kaçınılmazdır.

5. Veritabanı Dosyalarının Otomatik Büyümesi (Autogrowth)

Veritabanı dosyası dolduğunda ve SQL Server dosyayı fiziksel olarak büyütmeye (örneğin 1GB daha alan açmaya) çalıştığında, o anki tüm I/O işlemleri duraksayabilir.

  • Instant File Initialization (IFI) özelliği kapalıysa, SQL Server yeni açılan alanı sıfırlarla doldurmak zorundadır, bu da ciddi bir PAGEIOLATCH_EX bekleyişine yol açar.

PAGEIOLATCH_SH (Shared)

SQL Server bir veriyi RAM’de bulamadı → Diske gitti → Disk yavaş yanıt verdi → SQL Server bekledi →
Bu bekleme süresi = PAGEIOLATCH_SH

Bu bekleme tipi, doğrudan diskten veri okuma (I/O Read) ihtiyacından doğar. İşte buna neden olan temel işlemler:

1. Index / Table Scan (En Yaygın Sebep)

Eğer bir sorgu, ihtiyacı olan veriyi doğrudan bulabileceği bir index’e sahip değilse, tablonun veya mevcut bir index’in tamamını okumak zorunda kalır.

  • Örnek: 10 milyon satırlık bir tabloda, WHERE Sehir = ‘Ankara’ filtresiyle arama yapıyorsunuz ama Sehir kolonunda index yok. SQL Server milyonlarca sayfayı diskten belleğe çekmek zorunda kalır ve bu süreçte PAGEIOLATCH_SH tavan yapar.

2. Bellek Yetersizliği (Memory Pressure)

Sisteminizde yeterli RAM yoksa, SQL Server daha önce diskten okuyup belleğe koyduğu sayfaları, yeni gelen verilere yer açmak için bellekten siler (Flush).

  • Sorgu aynı veriyi 5 dakika sonra tekrar istediğinde, veri artık bellekte olmadığı için SQL Server tekrar diske gider. Bu kısır döngü (Churning), disk hızından bağımsız olarak sürekli bir bekleme yaratır.

3. İlk Kez Çalışan Sorgular (Cold Cache)

SQL Server servisi yeni başladığında veya DBCC DROPCLEANBUFFERS komutu ile bellek temizlendiğinde, Buffer Pool boştur. Çalıştırılan ilk büyük sorgular, tüm veriyi mecburen diskten getireceği için bu beklemeyi tetikler.

4. İstatistiklerin Güncel Olmaması

Eğer istatistikler eskiyse, SQL Server motoru 10 satır okuyacağını tahmin ederken aslında 1 milyon satırla karşılaşabilir. Yanlış tahmin, yanlış bir “Execution Plan” (Çalıştırma Planı) oluşturulmasına ve gereksiz yere devasa veri yığınlarının diskten okunmasına yol açar.

5. Paralel Sorgu Çalışması (CXPACKET ile Birlikte)

Büyük bir sorgu birden fazla işlemci çekirdeği (Thread) ile paralel çalışıyorsa, tüm bu thread’ler aynı anda farklı veri sayfalarını diskten talep eder. Bu yoğun okuma talebi, disk kuyruğunu (Disk Queue) şişirerek PAGEIOLATCH_SH süresini uzatır.

Sisteminizde bu bekleme tipinin yüksek olması her zaman diskinizin bozuk veya yavaş olduğu anlamına gelmez. Üç ana sebebi vardır:

  1. Kötü Sorgular (En Yaygın Sebep): Index olmadığı için SQL Server’ın 10 satır yerine 10 milyon satırı diskten okumak zorunda kalması (Table Scan).
  2. Bellek (RAM) Yetersizliği: RAM o kadar küçüktür ki, veriler belleğe girer girmez yer kalmadığı için atılır (Churning). SQL Server her seferinde aynı veriyi tekrar diskten okur.
  3. Yavaş Disk Altyapısı: Diskler gerçekten talebi karşılayamayacak kadar yavaştır (Yüksek Latency).

Sırasıyla şu adımları izleyerek sorunu kökten çözebilirsiniz:

A. Logical Reads değerinin düşürülmesi gerekmektedir

Diske gitmeden önce, sorgunun ne kadar veri istediğine bakın.

  • Eksik Indexleri Tamamlayın: Index Seek yapmak yerine Index Scan yapan sorgular disk yükünü katlar.
  • İstatistikleri Güncelleyin: Hatalı istatistikler SQL Server’ın yanlış ve büyük okumalar yapmasına neden olur.

B. Bellek (Memory) sağlığını kontrol edilmesi gerekmektedir.

  • Page Life Expectancy (PLE): Bu değer çok düşükse (genellikle 300 saniyenin altı tehlike sinyalidir), veriler bellekte kalamıyor demektir. Çözüm: RAM artırımı veya bellek tüketen sorguları optimize etmek.
  • Buffer Cache Hit Ratio: Bu değerin %95’in altında olması, verinin bellekte bulunamadığını ve diske gidildiğini doğrular.

C. Disk Gecikmesinin (Latency) ölçülmesi gerekmektedir

Eğer sorgular optimize ve RAM yeterliyse, donanımı şu DMV ile kontrol edin:

SELECT 
    DB_NAME(database_id) AS [Database Name], 
    file_id, 
    io_stall_read_ms / num_of_reads AS [Avg Read Latency (ms)],
    io_stall_write_ms / num_of_writes AS [Avg Write Latency (ms)]
FROM sys.dm_io_virtual_file_stats(NULL, NULL);
  • 1ms – 5ms: Mükemmel (SSD/NVMe).
  • 10ms – 20ms: Kabul edilebilir.
  • 20ms – 50ms: Yavaş, hissedilir gecikme.
  • 100ms+: Ciddi donanım veya yapılandırma sorunu.

Özet

AnalizBulgularÇözüm
Sorgu PlanıIndex Scan / Table ScanIndex ekle, sorguyu daralt.
PLE DeğeriÇok düşük (Sürekli dalgalanıyor)Max Server Memory kontrolü veya RAM ekleme.
Disk Latency50ms ve üzeriDiskleri kontrol et, RAID yapısını incele.

Başka makalede görüşmek dileğiyle..

“Dua ibadettir.”(Hadis)

Author: Yunus YÜCEL

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir