اگر تا به حال Execution Plan یک کوئری کند را بررسی کردهاید، احتمالاً با این وضعیت ناشی از Cardinality Estimation مواجه شدهاید:
Estimated Rows = 10
Actual Rows = 1,200,000
این اختلاف فاجعهبار معمولاً ریشه در همین مفهوم کلیدی دارد.
در SQL Server، Cardinality Estimator یا CE بخشی حیاتی از Query Optimizer است که تخمین میزند هر Operator در Execution Plan چه تعداد ردیف تولید خواهد کرد. این تخمین فقط یک عدد ساده نیست؛ بلکه پایه تمام تصمیمهای استراتژیک موتور پایگاه داده است. بنابراین اگر این تخمین اشتباه باشد، کل زنجیره تصمیمگیری دچار خطا میشود و در نهایت کوئری با افت شدید Performance اجرا خواهد شد.
در بسیاری از پروژههای سازمانی که لاندا تحلیل کرده است، ریشه کندیهای ظاهراً پیچیده دقیقاً به همین اختلاف Estimated و Actual Rows بازمیگردد، نه کمبود منابع سختافزاری.
Cardinality Estimation دقیقاً چیست؟
به زبان ساده، Cardinality Estimation فرآیندی است که طی آن Optimizer پیشبینی میکند در هر مرحله از اجرای Query چه تعداد ردیف تولید خواهد شد. این پیشبینی قبل از اجرای واقعی کوئری انجام میشود و کاملاً مبتنی بر آمار دادهها است.
Optimizer بر اساس این تخمین تصمیم میگیرد:
- از Nested Loop استفاده کند یا Hash Join
- Index Seek انجام دهد یا Scan
- چه مقدار Memory Grant تخصیص دهد
- Query بهصورت Parallel اجرا شود یا Serial
- ترتیب Joinها چگونه باشد
- آیا نیاز به Sort پرهزینه وجود دارد یا خیر
بنابراین CE در واقع ستون فقرات انتخاب Execution Plan است. اگر تخمین اشتباه باشد، تمام این تصمیمها نیز اشتباه خواهند بود.
چرا Cardinality Estimation اشتباه میشود؟
Statistics قدیمی یا ناکامل
Cardinality Estimator کاملاً به Statistics وابسته است. اگر Statistics قدیمی، ناقص یا غیرنماینده داده واقعی باشند، تخمین نیز نادرست خواهد بود.
موارد رایج شامل:
- فعال بودن Auto Update اما با Threshold دیرهنگام
- تغییر ناگهانی حجم داده
- بارگذاری Batchهای بزرگ اطلاعات
- Histogram که فقط بخشی از داده را پوشش میدهد.
در محیطهای OLTP با تغییرات سریع داده، این موضوع بسیار شایع است.
Data Skew یا توزیع نامتوازن داده
فرض کنید:
۹۰٪ دادهها Status = ‘Active’
۱۰٪ دادهها Status = ‘Inactive’
اگر Optimizer فرض کند توزیع یکنواخت است، تخمین برای فیلتر روی Active بهشدت اشتباه خواهد بود. این خطا بهخصوص در ستونهایی با توزیع نامتقارن بسیار رایج است و باعث انتخاب Join اشتباه میشود.
Correlated Columns یا وابستگی آماری ستونها
SQL Server بهصورت پیشفرض فرض استقلال آماری بین ستونها را در نظر میگیرد، مگر اینکه Statistics ترکیبی وجود داشته باشد.
مثال:
Country = ‘Iran’
City = ‘Tehran’
در واقع این دو ستون وابستهاند، اما اگر Statistics جداگانه باشند، CE رابطه را درک نمیکند و حاصل ضرب Selectivityها را محاسبه میکند که معمولاً بسیار کمتر از مقدار واقعی خواهد بود.
Parameter Sniffing
در Stored Procedureها، اولین مقدار پارامتر که Query Compile میشود، مبنای ساخت Plan قرار میگیرد. اگر آن مقدار نماینده کل داده نباشد، Plan تولیدشده برای مقادیر دیگر کاملاً نامناسب خواهد بود.
نتیجه مستقیم این وضعیت:
Estimated Rows اشتباه
انتخاب Join نامناسب
افزایش شدید Logical Reads
کندی غیرقابل پیشبینی
تغییر نسخه Cardinality Estimator
از SQL Server 2014 به بعد، مدل جدید CE معرفی شد. این مدل رفتار متفاوتی نسبت به Legacy CE دارد و در Compatibility Levelهای مختلف فعال میشود.
در برخی سیستمها، ارتقا نسخه بدون بررسی Execution Plan باعث تغییر ناگهانی استراتژی Join و افت Performance شده است. بنابراین Upgrade بدون تحلیل CE میتواند پرریسک باشد.
تأثیر تخمین اشتباه بر Performance
انتخاب Join اشتباه
اگر تخمین کم باشد، Optimizer معمولاً Nested Loop را انتخاب میکند. اما اگر تعداد واقعی ردیفها بسیار زیاد باشد، میلیونها Lookup رخ میدهد و سرور تحت فشار شدید قرار میگیرد.
Memory Grant نادرست
تخمین کم → کمبود Memory → Spill به TempDB
تخمین زیاد → تخصیص بیشازحد Memory → کاهش Concurrency
هر دو حالت برای محیطهای سازمانی خطرناک هستند.
Parallelism نامناسب
اگر CE تخمین بیشازحد بدهد، Query ممکن است بیدلیل Parallel شود و CPU مصرف کند. برعکس، اگر تخمین کم باشد، Parallelism فعال نمیشود در حالی که لازم بوده است.
انتخاب Index اشتباه
گاهی Optimizer به دلیل تخمین کم، Index Seek را انتخاب میکند، در حالی که به دلیل حجم واقعی داده، Scan کارآمدتر بوده است. نتیجه، افزایش Logical Reads و کاهش Throughput خواهد بود.
چگونه تشخیص دهیم مشکل از CE است؟
در Execution Plan به موارد زیر توجه کنید:
✔ اختلاف شدید Estimated Rows و Actual Rows
✔ وجود Warning مربوط به Spill
✔ Memory Grant غیرمنطقی
✔ Join Strategy نامتناسب با حجم واقعی داده
✔ اختلاف بیش از ۱۰ برابر بین تخمین و مقدار واقعی
اگر این علائم وجود داشته باشد، احتمالاً ریشه مشکل در Cardinality Estimation است.
تفاوت CE قدیم و جدید
CE قدیم یا Legacy:
- فرض استقلال بین ستونها
- رفتار محافظهکارانهتر
- مناسب برخی Workloadهای قدیمی
CE جدید:
- مدل آماری پیشرفتهتر
- تغییر در نحوه تخمین Join و Predicate
- رفتار متفاوت در Queryهای پیچیده
هیچکدام مطلقاً بهتر نیستند. انتخاب صحیح به Data Pattern و نوع Workload بستگی دارد و باید مبتنی بر تست کنترلشده انجام شود.
راهکارهای اصلاح مشکل Cardinality Estimation
بهروزرسانی دقیق Statistics
UPDATE STATISTICS TableName WITH FULLSCAN;
در جداول حیاتی، استفاده از FULLSCAN میتواند دقت تخمین را افزایش دهد.
ایجاد Multi-Column Statistics
در صورت وجود وابستگی بین ستونها، Statistics ترکیبی ایجاد کنید تا CE رابطه را بهتر درک کند.
مدیریت Parameter Sniffing
استفاده هدفمند از:
- OPTIMIZE FOR
- RECOMPILE
- Plan Guide
- Query Store
البته این اقدامات باید پس از تحلیل دقیق انجام شود، نه بهصورت عمومی.
استفاده هدفمند از Hintها
OPTION (USE HINT('FORCE_LEGACY_CARDINALITY_ESTIMATION'))
این روش فقط در شرایط خاص توصیه میشود و جایگزین تحلیل ریشهای نیست.
استفاده از Query Store
با Query Store میتوان Planهای مختلف را مقایسه و Plan پایدار را Force کرد. این ابزار در تحلیل تغییر رفتار CE بعد از Upgrade بسیار ارزشمند است.
چه زمانی مشکل CE بحرانی میشود؟
- اختلاف شدید Estimated و Actual Rows
- Spill مکرر در TempDB
- ناپایداری Performance در ساعات مختلف
- کندی پس از Upgrade نسخه
- افزایش ناگهانی CPU بدون تغییر حجم داده
در چنین شرایطی، مشکل معمولاً ساختاری است و با افزودن Index یا افزایش سختافزار حل نمیشود.
اشتباهات رایج سازمانها
❌ افزایش CPU و RAM بدون تحلیل Execution Plan
❌ افزودن Indexهای متعدد بدون بررسی CE
❌ استفاده گسترده و غیرتحلیلی از Hint
❌ غیرفعال کردن CE جدید بدون Benchmark
❌ نادیده گرفتن Data Skew
این اقدامات معمولاً مشکل را پنهان میکنند، نه حل.

نتیجهگیری
Cardinality Estimation قلب تصمیمگیری Query Optimizer است. اگر تخمین اشتباه باشد، Execution Plan اشتباه خواهد بود و در نتیجه Performance پایدار نخواهد ماند.
بسیاری از کندیهای مرموز SQL Server نه به دلیل ضعف سختافزار، بلکه به دلیل تخمین آماری نادرست رخ میدهند. بنابراین رویکرد حرفهای در Tuning، تمرکز بر تحلیل CE، Statistics و الگوی داده است.
خدمات تخصصی Tuning در لاندا
اگر در سازمان شما:
- اختلاف Estimated و Actual Rows زیاد است.
- پس از Upgrade نسخه با افت Performance مواجه شدهاید.
- Spill به TempDB مشاهده میشود.
- Execution Planها ناپایدار هستند.
- مصرف CPU غیرقابل پیشبینی است.
تیم تخصصی لاندا با تحلیل عمیق Execution Plan، بررسی مدل Cardinality Estimation، تحلیل Statistics و طراحی راهکار ساختاری، مشکل Performance را بهصورت ریشهای و پایدار برطرف میکند.
برای دریافت خدمات Tuning پیشرفته SQL Server و تحلیل تخصصی Query Optimizer، با کارشناسان لاندا تماس ✆ بگیرید و زیرساخت داده سازمان خود را به سطحی حرفهای ارتقا دهید.


بدون دیدگاه