راهنمای جامع Wait Statistics در SQL Server؛ از آمار تجمعی تا انتظار زنده
Wait Statistics یکی از قابلاعتمادترین نقطههای شروع برای بررسی کندی SQL Server است، زیرا نشان میدهد Taskهای موتور زمان خود را در انتظار چه منابع یا هماهنگیهایی گذراندهاند. این راهنما پنج DMV کلیدی را به یک جریان تشخیص منظم وصل میکند تا بهجای درمان حدسی، از نشانه به شواهد و سپس به علت ریشهای برسیم.
هدف تحلیل Wait، پیدا کردن بزرگترین عدد و اعمال یک نسخه ثابت نیست. هر مقدار باید در چارچوب بازه زمانی، شدت بار، Uptime، نسخه SQL Server، معماری برنامه و تجربه واقعی کاربر تفسیر شود. Wait Type نام مسیر بررسی است و نه حکم نهایی.
اصل طلایی: ابتدا بازه مسئله را دقیق کنید، سپس Delta انتظارها را بسنجید و فقط پس از همبستگی با Query، Plan، I/O، CPU و Blocking تغییر اعمال کنید.
دسترسی سریع به مقالههای تخصصی
Wait دقیقاً چگونه شکل میگیرد؟
یک Request در SQL Server به Taskها شکسته میشود. Task زمانی روی Scheduler اجرا میشود که Worker و CPU در اختیار داشته باشد. اگر برای صفحه داده، قفل، Log Flush، حافظه، پیام شبکه یا ساختار داخلی آماده نباشد، وارد وضعیت انتظار میشود و نوع آن انتظار ثبت میگردد.
زمان Wait معمولاً دو بخش مفهومی دارد: زمان انتظار منبع و زمان Signal. در بخش منبع، Task منتظر آماده شدن I/O، Lock یا رویدادی دیگر است. پس از آماده شدن منبع، Task ممکن است در صف Runnable بماند تا CPU دریافت کند؛ این بخش Signal Wait است.
یک Query میتواند چند نوع انتظار تجربه کند و یک Wait Type نیز میتواند از چند علت ایجاد شود. برای نمونه، PAGEIOLATCH میتواند با کمبود حافظه، Scan حجیم، Latency Storage یا بار همزمان مرتبط باشد. بنابراین رابطه یکبهیک میان نام Wait و نسخه درمان وجود ندارد.
آمار تجمعی برای ساخت Baseline و تعیین الگوی غالب مناسب است، در حالی که DMV لحظهای برای دیدن وضعیت Incident جاری ارزش دارد. اتصال این دو دید، خطای ناشی از یک Snapshot تصادفی را کاهش میدهد.
Uptime اهمیت بنیادی دارد. صد ساعت زمان انتظار روی سروری با چند ماه فعالیت ممکن است طبیعی باشد، ولی همان مقدار در ده دقیقه یک تغییر شدید است. زمان شروع سرویس و Reset Counterها باید بخشی از هر گزارش باشد.
طبقهبندی کاربردی انتظارها
| خانواده | نمونه نشانه | شواهد تکمیلی | احتیاط در تفسیر |
|---|
| CPU و Scheduler | Signal Wait و SOS_SCHEDULER_YIELD | CPU سیستمعامل، Runnable Queue، Plan | بالا بودن CPU میتواند پیامد Query ناکارآمد باشد. |
| I/O داده | PAGEIOLATCH | Latency فایل، Buffer Pool، Scanها | فقط Storage مقصر نیست؛ حافظه و Plan را ببینید. |
| Transaction Log | WRITELOG | Log Flush، اندازه تراکنش، VLF | Commitهای ریز و دیسک Log هر دو مؤثرند. |
| Lock و Blocking | LCK_M_* | Blocking Chain، تراکنش باز، ایندکس | Kill بدون بررسی Rollback خطرناک است. |
| Parallelism | CXPACKET و CXCONSUMER | Plan، DOP، Skew، CPU | وجود Parallelism ذاتاً مشکل نیست. |
| شبکه و مصرفکننده | ASYNC_NETWORK_IO | سرعت خواندن Client، Result Set | شبکه تنها علت ممکن نیست. |
| داخلی موتور | Latch و Spinlock | Build، workload، Counterهای داخلی | تغییرات غیرمستند ریسک بالایی دارند. |
این طبقهبندی برای ساخت فرضیه است. پس از دیدن یک خانواده، باید Queryهای پرمصرف، Execution Plan، وضعیت فایلها، Transactionها و تغییرات اخیر بررسی شوند. اگر چند خانواده همزمان رشد کردهاند، Timeline مشترک کمک میکند علت بالادستی را پیدا کنیم.
جریان حرفهای تحلیل از نشانه تا علت
مرحله نخست تعریف دقیق رخداد است: چه کاربری، در چه بازهای، کدام عملیات و با چه تغییر Latency یا Throughput مواجه شده است. عبارت کلی «دیتابیس کند است» برای نمونهبرداری هدفمند کافی نیست.
در مرحله دوم Snapshot تجمعی، Uptime و شاخصهای سیستمعامل ثبت میشوند. اگر Baseline موجود باشد، Delta رخداد با بازه عادی همان روز و ساعت مقایسه میشود. مقدار مطلق و درصد هر دو لازماند.
در مرحله سوم خانواده انتظار غالب به شواهد تخصصی وصل میشود. I/O به آمار فایل و Plan، Lock به Blocking Chain و Transaction، CPU به Scheduler و Queryهای پرمصرف، و انتظار داخلی به Build و Counterهای مرتبط میرسد.
مرحله چهارم ساخت فرضیه قابلآزمایش است. برای مثال «Scan جدول سفارشها باعث افزایش خواندن و PAGEIOLATCH شده» فرضیهای است که با Plan، Logical Reads و آزمایش ایندکس قابل سنجش است؛ «دیسک کند است» هنوز کلی است.
در مرحله پنجم کمریسکترین تغییر انتخاب و پیش از اجرا معیار موفقیت تعیین میشود. پس از تغییر، همان Queryها و همان بازه با Baseline مقایسه میشوند و در صورت نبود اثر، تغییر بازگردانی یا فرضیه اصلاح میشود.
آخرین مرحله مستندسازی است. Snapshot ID، Query، Plan، تنظیم تغییرکرده، نتیجه و تصمیم تیم باید ثبت شود تا رخداد بعدی از صفر آغاز نشود و دانش عملیاتی پایدار بماند.
- تعریف بازه و اثر کاربری
- ثبت Snapshot و Uptime
- محاسبه Delta و نرخ
- اتصال خانواده Wait به شواهد مکمل
- آزمایش یک تغییر کمریسک
- اندازهگیری پس از تغییر و مستندسازی
مثالهای عملی یکپارچه
مثال ۱: ساخت نمای اولیه Waitهای کل نمونه
برای آغاز Triage، انتظارهای دارای زمان مثبت مرتب میشوند تا خانوادههای غالب دیده شوند.
SELECT TOP (10)
wait_type,
waiting_tasks_count,
wait_time_ms,
signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_time_ms > 0
ORDER BY wait_time_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| wait_type | wait_time_ms |
| WRITELOG | 92000 |
| PAGEIOLATCH_SH | 68400 |
این Snapshot فقط جهت حرکت بعدی را مشخص میکند و باید به Delta و شواهد مکمل برسد.
مثال ۲: مشاهده انتظارهای زنده و Blocker
در Incident جاری، Taskهای مسدودشده با شناسه Blocker مثبت نمایش داده میشوند.
SELECT
session_id,
blocking_session_id,
wait_type,
wait_duration_ms
FROM sys.dm_os_waiting_tasks
WHERE blocking_session_id > 0
ORDER BY wait_duration_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| session_id | blocking_session_id |
| 87 | 63 |
| 88 | 63 |
پیش از اقدام روی Blocker وضعیت تراکنش، کاربر و هزینه Rollback را بررسی کنید.
مثال ۳: یافتن Sessionهای پرانتظار
جمع کردن Waitها در سطح Session اتصالهایی را که در عمر خود زمان انتظار بیشتری داشتهاند مشخص میکند.
SELECT TOP (10)
session_id,
SUM(wait_time_ms) AS total_wait_ms
FROM sys.dm_exec_session_wait_stats
GROUP BY session_id
ORDER BY total_wait_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| session_id | total_wait_ms |
| 81 | 93200 |
| 64 | 71500 |
عمر Session و Connection Pool را کنار این مقدار ببینید تا اتصال قدیمی بهاشتباه مقصر اعلام نشود.
مثال ۴: رتبهبندی Latch Classها
برای بررسی رقابت داخلی، زمان و تعداد Latchها در یک خروجی قرار میگیرد.
SELECT TOP (10)
latch_class,
waiting_requests_count,
wait_time_ms,
max_wait_time_ms
FROM sys.dm_os_latch_stats
WHERE wait_time_ms > 0
ORDER BY wait_time_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| latch_class | wait_time_ms |
| ACCESS_METHODS_DATASET_PARENT | 48200 |
| BUFFER | 19300 |
Latch را با Lock یکی ندانید و نسخه موتور را در تفسیر نام کلاس لحاظ کنید.
مثال ۵: رتبهبندی Spinlockها بر اساس Backoff
Backoffهای زیاد میتوانند مسیر پیشرفته بررسی همزمانی داخلی را نشان دهند.
SELECT TOP (10)
name,
collisions,
spins,
backoffs
FROM sys.dm_os_spinlock_stats
WHERE backoffs > 0
ORDER BY backoffs DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| name | backoffs |
| LOCK_HASH | 9200 |
| SOS_CACHESTORE | 4100 |
مقدار تجمعی بدون نرخ، CPU و Baseline دلیل کافی برای تغییر تنظیمات داخلی نیست.
مثال ۶: ثبت زمان مشترک برای Triage چندلایه
یک زمان UTC مشترک به خروجیهای مختلف اجازه میدهد در گزارش Incident روی یک Timeline قرار گیرند.
DECLARE @CapturedAtUtc datetime2(3) = SYSUTCDATETIME();
SELECT TOP (5)
@CapturedAtUtc AS captured_at_utc,
wait_type,
wait_time_ms
FROM sys.dm_os_wait_stats
ORDER BY wait_time_ms DESC;
SELECT TOP (5)
@CapturedAtUtc AS captured_at_utc,
session_id,
wait_type,
wait_duration_ms
FROM sys.dm_os_waiting_tasks
ORDER BY wait_duration_ms DESC;
| ستون یا شاخص | خروجی نمونه |
|---|
| captured_at_utc | لایهها |
| 2026-07-22 08:45:00 | تجمعی و زنده |
در سامانه واقعی Snapshot ID، نام سرور، Uptime و شناسه Incident را نیز ذخیره کنید.
خطاهای رایج در تحلیل Wait Statistics
- مرتب کردن Counter تجمعی و اعلام اولین ردیف بهعنوان علت قطعی.
- استفاده از فهرست حذف Wait Typeهای یک مقاله قدیمی بدون بررسی نسخه فعلی.
- نادیده گرفتن Reset یا Restart میان دو Snapshot و محاسبه Delta نامعتبر.
- بهینهسازی درصد بزرگی که مقدار مطلق و اثر کاربری آن ناچیز است.
- اجرای تنظیمات Server-wide یا Trace Flag قبل از تحلیل Query و Plan.
- جمعآوری بسیار پرتکرار متن و Plan همه Sessionها و ایجاد سامانه مانیتورینگ پرهزینه.
- ندیدن رخدادهای Deploy، Backup، ETL و نگهداری روی Timeline.
راه جلوگیری از این خطاها تعریف قرارداد داده مانیتورینگ است: هر Snapshot باید زمان UTC، سرور، نسخه، Uptime، بازه، منبع Counter و وضعیت Reset را داشته باشد. گزارش بدون این Metadata برای تصمیم مهم کافی نیست.
نکات کارایی و طراحی سامانه مانیتورینگ
خواندن DMVهای اصلی معمولاً سبک است، اما طراحی Collector میتواند سنگین شود. ستونهای لازم را انتخاب کنید، Interval را از نیاز تشخیص استخراج کنید و دریافت Plan یا متن کامل را فقط برای Candidateهای محدود انجام دهید.
داده خام را از داده مشتقشده جدا نگه دارید. Snapshot خام امکان محاسبه دوباره Delta و اصلاح منطق فیلتر را فراهم میکند، در حالی که ذخیره فقط درصد نهایی قابلیت ممیزی را کاهش میدهد.
برای Retention چندلایه طراحی کنید: داده ریزدانه برای روزهای اخیر، Rollup ساعتی برای چند ماه و خلاصه Baseline برای روند بلندمدت. این ساختار حجم را کنترل و تحلیل Incident را حفظ میکند.
Collector نباید در زمان فشار خود به گلوگاه تبدیل شود. Timeout، خطای مجوز، Restart، Failover و کاهش Counter باید بهعنوان وضعیت داده ثبت شوند، نه اینکه با صفر جایگزین گردند.
Alert را فقط از عبور یک Wait از عدد ثابت نسازید. ترکیب نرخ Wait، انحراف از Baseline، Latency کاربر و مدت پایداری هشدارهای قابلاقدامتری تولید میکند.
بهترین روشها
- همیشه مقدار، نرخ، تعداد و درصد را با هم نگه دارید.
- برای مقایسه از Delta بازههای همنوع و Uptime معتبر استفاده کنید.
- Wait Type را نشانه بدانید و علت را با Plan و متریک مکمل اثبات کنید.
- مجوز مشاهده DMV را بر اساس کمترین دسترسی لازم واگذار کنید.
- نسخه و Build SQL Server را در Runbook تشخیص ثبت کنید.
- پیش از Kill، Clear یا تغییر Server-wide تأیید عملیاتی بگیرید.
- نتیجه تغییر را با شاخص کاربری و نه فقط Counter داخلی بسنجید.
سؤالات متداول
پرسش ۱: Wait Statistics در SQL Server چیست؟
مدت و تعداد توقف Taskها هنگام انتظار برای منبع، CPU یا هماهنگی داخلی است. این داده زبان مشترکی برای تشخیص مبتنی بر شواهد فراهم میکند.
پرسش ۲: از کدام DMV باید شروع کنیم؟
برای نمای کلان از sys.dm_os_wait_stats، برای Session از sys.dm_exec_session_wait_stats و برای رخداد زنده از sys.dm_os_waiting_tasks شروع کنید. Latch و Spinlock مراحل تخصصیترند.
پرسش ۳: تحلیل Waitها چگونه به کاهش هزینه کمک میکند؟
پیش از خرید سختافزار یا بازنویسی گسترده نشان میدهد گلوگاه محتمل CPU، I/O، Lock، Log یا مسیر دیگری است و سرمایهگذاری را هدفمند میکند.
پرسش ۴: برای یک داشبورد سازمانی چه شاخصهایی لازم است؟
Delta زمان، نرخ رخداد، Resource و Signal، Uptime، Throughput، Latency و رخدادهای Deploy باید روی یک Timeline ارائه شوند.
پرسش ۵: تفاوت Snapshot تجمعی و زنده چیست؟
Snapshot تجمعی تاریخچه از آغاز Counterها را خلاصه میکند؛ نمای زنده فقط Taskهایی را نشان میدهد که همان لحظه منتظرند.
پرسش ۶: چه زمانی از خدمات تخصصی Performance Tuning استفاده کنیم؟
وقتی Wait غالب مشخص است اما ارتباط آن با Query، Plan، معماری یا زیرساخت روشن نیست، تحلیل تخصصی ریسک تغییر و زمان Incident را کم میکند.
پرسش ۷: رایجترین خطای تحلیل Wait چیست؟
درمان نام Wait بدون بررسی Delta و Context است. Wait نشانه است و علت ریشهای باید با چند منبع شواهد تأیید شود.
پرسش ۸: آیا جمعآوری DMVها سربار زیادی دارد؟
Queryهای هدفمند معمولاً سبکاند، اما Polling سریع، Join متن و Plan برای همه Sessionها و ذخیره بیحد میتواند سربار و حجم بسازد.
پرسش ۹: بهترین روش نگهداری Baseline چیست؟
Snapshot زماندار با Uptime و متریک بار را در دورههای مشابه نگه دارید، صدکها را محاسبه و تغییرات Deploy و نگهداری را ثبت کنید.
پرسش ۱۰: آیا این روش در همه نسخههای SQL Server یکسان است؟
اصل روش ثابت است، ولی Wait Typeها، ستونها و مجوزها تغییر میکنند. مستندات رسمی نسخه و محیط، بهویژه SQL Server 2022 و سرویسهای مدیریتشده، باید کنترل شود.
سؤالات مصاحبهای Wait Statistics
چرا Delta از مقدار تجمعی مهمتر است؟
زیرا فعالیت بازه مسئله را از تاریخچه قدیمی جدا میکند و امکان همبستگی با رخداد کاربر را میدهد. پاسخ کامل باید Restart و Reset را نیز پوشش دهد.
Resource Wait و Signal Wait چه تفاوتی دارند؟
اولی انتظار آماده شدن منبع و دومی زمان ماندن Task آماده در صف CPU است. این تفکیک مسیر بررسی I/O یا Lock را از فشار Scheduler جدا میکند.
چگونه Blocking زنده را از تاریخچه Wait تشخیص میدهید؟
برای وضعیت زنده از waiting_tasks و requests استفاده میکنیم و برای الگوی تجمعی به wait_stats و session_wait_stats رجوع میکنیم. Extended Events تاریخچه رخدادهای کوتاه را تکمیل میکند.
چرا یک فهرست ثابت Waitهای قابل حذف خطرناک است؟
نسخه، قابلیتها و معماری تغییر میکنند و یک Wait ممکن است در محیطی پسزمینه و در محیط دیگر شاخص باشد. فهرست باید مستند و بازبینی شود.
در چه شرایطی Spinlock را بررسی میکنید؟
پس از اثبات فشار قابلتکرار و کنار گذاشتن علتهای رایج، هنگامی که Delta Backoff با CPU و افت Throughput همبسته است و Build نیز بررسی شده باشد.
معیار موفقیت یک اصلاح Performance چیست؟
کاهش Latency یا افزایش Throughput در بار قابل مقایسه، بدون عارضه جانبی. کاهش یک Wait داخلی بهتنهایی معیار کافی نیست.
چکلیست نهایی
- بازه و اثر کاربری مشخص است.
- Uptime و Reset Counter ثبت شده است.
- Delta معتبر محاسبه شده است.
- Waitهای پسزمینه با منطق نسخهپذیر مدیریت شدهاند.
- شواهد مکمل Query، Plan و منابع جمع شدهاند.
- تغییر کمریسک و معیار موفقیت تعریف شده است.
- اندازهگیری پس از تغییر انجام و نتیجه مستند شده است.
جمعبندی و مسیر مطالعه
Wait Statistics به DBA و تیم توسعه کمک میکند زمان از دسترفته را طبقهبندی و بررسی را اولویتبندی کنند. ارزش واقعی زمانی ایجاد میشود که Counterها در بازه معتبر، با Baseline و اثر کاربری تحلیل شوند و هر فرضیه با شواهد مستقل آزموده شود.
برای ادامه، ابتدا مقاله آمار کل نمونه را بخوانید، سپس بر اساس نیاز به Session یا Incident زنده حرکت کنید. مقالههای Latch و Spinlock برای مرحله پیشرفته و مسائل داخلی موتور مناسباند.