Bu makalede SQL Server’da bekleme tiplerini (wait types) takip edip, belirli aralıklarla bunları bir tabloya loglayan ve sonra bu verileri analiz etmeni sağlayacak bir yapı kuracağız.
Yapılması gerekenler:
- Belirli aralıklarla sistemdeki bekleme tiplerini toplamak
- Bunları bir tabloya kaydetmek
- Sonradan analiz edip en çok hangi beklemelerin yaşandığını görebilmek
Aşağıda kurulacak yapıda kullanacağımız genel ifadeleri görebilirsin.
- sys.dm_os_wait_stats: SQL Server’daki bekleme istatistiklerini verir.
- Bu DMV’den alınan verileri belli aralıklarla bir tabloya kaydedeceğiz.
- Her çalıştırmada zaman damgası ile birlikte log tutulacak
- İstersen bunu SQL Agent Job ile belirli aralıklarda çalıştırabilirsin (1 dk / 5 dk)
İlk olarak bir log tablosu oluşturulur. Aynı isimde log tablosu varsa silip tekrardan bir log tablosu oluşturur.
USE [master]; -- İstersen kendi veritabanında oluştur
IF OBJECT_ID('dbo.WaitStatsLog') IS NOT NULL DROP TABLE dbo.WaitStatsLog;
CREATE TABLE dbo.WaitStatsLog (
log_time DATETIME NOT NULL DEFAULT GETDATE(),
wait_type NVARCHAR(120),
waiting_tasks_count BIGINT,
wait_time_ms BIGINT,
max_wait_time_ms BIGINT,
signal_wait_time_ms BIGINT
);
Yukarıda oluşturulan tabloda sorgu performansını artırmak için tablo oluşturulduktan sonra aşağıdaki iki index oluşturulabilir.
CREATE NONCLUSTERED INDEX IX_WaitStatsLog_logtime
ON dbo.WaitStatsLog (log_time);
CREATE NONCLUSTERED INDEX IX_WaitStatsLog_waittype
ON dbo.WaitStatsLog (wait_type);

Bekleyen verileri log tablomuza aşağıdaki script ile yazabiliriz. Bu scripti bir job aracılığıyla belirli zaman belirlenerek çalıştırılabilir.
-- Wait statistics'i loga yaz
INSERT INTO dbo.WaitStatsLog (log_time, wait_type, waiting_tasks_count, wait_time_ms, max_wait_time_ms, signal_wait_time_ms)
SELECT
GETDATE(),
wait_type,
waiting_tasks_count,
wait_time_ms,
max_wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE',
'SLEEP_TASK', 'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH',
'WAITFOR', 'LOGMGR_QUEUE', 'CHECKPOINT_QUEUE',
'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT', 'XE_DISPATCHER_JOIN',
'BROKER_TO_FLUSH', 'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT',
'CLR_AUTO_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
'BROKER_EVENTHANDLER', 'TRACEWRITE', 'XE_DISPATCHER_WAIT',
'BROKER_RECEIVE_WAITFOR', 'REPUBLISH_QUEUE', 'PREEMPTIVE_OS_GETPROCADDRESS',
'PREEMPTIVE_OS_AUTHENTICATIONOPS'
);
DELETE FROM dbo.WaitStatsLog
WHERE log_time < DATEADD(DAY, -7, GETDATE());
Not: Önemsiz ve sistemsel bekleme tipleri NOT IN komutuyla dahil edilmedi.
Not: Delete komutuyla job her çalıştırıldıktan sonra 7 gün önceki verileri tablodan silmektedir.
- wait_type: Beklemenin adı (örnek: PAGEIOLATCH_SH, SOS_SCHEDULER_YIELD). Hangi tür işlemin beklediğini gösterir.
- waiting_tasks_count: Bu bekleme tipine giren toplam işlem sayısı
- wait_time_ms: Bu bekleme tipi için toplam beklenen süre (milisaniye olarak).
- max_wait_time_ms: Bu türdeki beklemelerden en uzun sürenin süresi (milisaniye cinsinden).
- signal_wait_time_ms: İşlem beklemesini bitirmiş ama CPU’ya erişmek için beklemiş süre. (Yani sistemde CPU darboğazı var mı gösterir.)

Diyelim ki son 2 saatte en çok beklenen wait type’ları görmek istiyorsanız aşağıdaki sorgu kullanılır.
SELECT
wait_type,
COUNT(*) AS entry_count, -- loglanan kayıt sayısı
SUM(waiting_tasks_count) AS total_tasks, -- toplam bekleyen görev sayısı
SUM(wait_time_ms) / 1000.0 AS total_wait_seconds,-- toplam bekleme süresi (saniye)
AVG(wait_time_ms) / 1000.0 AS avg_wait_seconds -- ortalama bekleme süresi (saniye)
FROM dbo.WaitStatsLog
WHERE log_time >= DATEADD(HOUR, -2, GETDATE())
--AND wait_type = 'PAGEIOLATCH_SH'--Bekleme türüne göre ek filtreleme koyulabilir.
GROUP BY wait_type
ORDER BY total_wait_seconds DESC;
- COUNT(*) → Bu wait_type kaç kez loglandı
- SUM(waiting_tasks_count): Bu bekleme türüne giren toplam işlem sayısı
- SUM(wait_time_ms) → Tüm kayıtlar için toplam bekleme süresi
- AVG(wait_time_ms) → Ortalama bekleme süresi (performans analizi için çok önemli)

Belirli bir zaman dilimi arasındaki bekleme tiplerini görmek için aşağıdaki komut kullanılmaktadır.
SELECT [log_time]
,[wait_type]
,[waiting_tasks_count]
,[wait_time_ms]
,[max_wait_time_ms]
,[signal_wait_time_ms]
FROM [master].[dbo].[WaitStatsLog] where log_time between '2025-04-20 20:08:50.993' and '2025-04-20 20:08:50.993'
Başka bir makalede görüşmek dileğiyle..
“Göklerde ve yerde olan her şey yalnız Allah’ındır; kuşkusuz hiçbir şeye ihtiyacı olmayan ve her türlü övgüye lâyık olan yalnız Allah’tır.”Lokman-26