Low Selectivity SQL Server, ایندکس بی‌اثر, Index Performance, Query Tuning SQL Server, طراحی ایندکس, DBA حرفه‌ای, Execution Plan, Index Scan, Index Seek

ر بسیاری از پروژه‌های SQL Server، به‌ویژه در سازمان‌هایی که چند سال از عمر دیتابیس آن‌ها گذشته، یک گزاره‌ی تکراری شنیده می‌شود:
«ما روی این ستون ایندکس داریم، پس مشکل Performance نباید از اینجا باشد».

با این حال، وقتی Execution Plan بررسی می‌شود، Index Seek دیده نمی‌شود، Scanها پرتکرارند، CPU بی‌دلیل بالا می‌رود و Query Store پر از Planهای متناقض است.
این تناقض ظاهری، معمولاً نه از کمبود ایندکس، بلکه از Low Selectivity ناشی می‌شود؛ مفهومی که زیاد نام برده می‌شود، اما کمتر به‌درستی فهمیده می‌شود.

Low Selectivity یعنی ایندکسی که از نظر فیزیکی وجود دارد، اما از نظر منطقی برای Optimizer ارزش تصمیم‌سازی ندارد.
در این مقاله، به‌صورت دقیق، تحلیلی و عملیاتی بررسی می‌کنیم Low Selectivity چیست، چرا ایندکس‌ها را بی‌اثر می‌کند، چگونه باعث Scan می‌شود، چه نشانه‌هایی در سیستم دارد و مهم‌تر از همه، چگونه باید با آن برخورد حرفه‌ای کرد.

Selectivity دقیقاً چیست و چرا Optimizer به آن حساس است؟

Selectivity معیاری است برای سنجش توان یک ستون در محدودکردن داده‌ها.
هرچه مقادیر یک ستون متنوع‌تر و توزیع آن یکنواخت‌تر باشد، Selectivity بالاتر می‌رود.
در مقابل، هرچه تعداد مقادیر تکراری بیشتر شود، Selectivity کاهش پیدا می‌کند.

به‌بیان ساده:

  • ستونی با میلیون‌ها مقدار یکتا → High Selectivity

  • ستونی با چند مقدار پرتکرار → Low Selectivity

اما نکته‌ی کلیدی اینجاست:
Optimizer به وجود ایندکس اهمیت نمی‌دهد؛ به «صرفه‌ی استفاده از آن» اهمیت می‌دهد.

SQL Server هنگام ساخت Execution Plan از خود می‌پرسد:
«آیا استفاده از این ایندکس واقعاً حجم داده‌ی خوانده‌شده را کاهش می‌دهد، یا فقط یک مسیر اضافی و پرهزینه ایجاد می‌کند؟»

اگر پاسخ منفی باشد، حتی بهترین ایندکس هم کنار گذاشته می‌شود.

چرا Low Selectivity ایندکس را از نظر اقتصادی بی‌ارزش می‌کند؟

Optimizer همیشه به‌دنبال کم‌هزینه‌ترین مسیر است.
وقتی یک ستون Selectivity پایینی دارد، استفاده از ایندکس معمولاً مزیت مشخصی ایجاد نمی‌کند، زیرا:

  • بخش بزرگی از جدول همچنان باید خوانده شود

  • Random I/O افزایش پیدا می‌کند

  • هزینه‌ی Seek به‌علاوه Lookup از یک Scan ساده بیشتر می‌شود

در چنین شرایطی، SQL Server به‌جای Index Seek، سراغ Table Scan یا Index Scan می‌رود.
در نتیجه، تیم فنی تصور می‌کند ایندکس «نادیده گرفته شده»، در حالی که Optimizer تصمیم منطقی گرفته است.

ایندکس از نظر فیزیکی وجود دارد، اما از نظر اقتصادی ارزش مصرف ندارد.

مثال واقعی از Low Selectivity در دیتابیس‌های سازمانی

فرض کنید جدولی با ۵۰ میلیون رکورد دارید و ستونی به نام IsActive که فقط دو مقدار دارد:

  • ۱ (فعال)

  • ۰ (غیرفعال)

۹۵٪ رکوردها مقدار ۱ دارند.
حال، روی این ستون ایندکس می‌سازید و Query زیر را اجرا می‌کنید:

SELECT *
FROM Orders
WHERE IsActive = ۱

از دید Optimizer:

  • باید تقریباً کل جدول را بخواند

  • ایندکس فقط یک مسیر اضافی ایجاد می‌کند

  • Scan ساده‌تر، سریع‌تر و قابل پیش‌بینی‌تر است

در نتیجه، ایندکس کنار گذاشته می‌شود.
این تصمیم اشتباه نیست؛ طراحی ایندکس اشتباه بوده است.

اشتباه رایج و پرهزینه: «روی هر WHERE ایندکس بساز»

یکی از مخرب‌ترین توصیه‌های سطحی در SQL Server همین جمله است.
بسیاری از تیم‌ها بدون تحلیل Selectivity، روی هر ستونی که در WHERE می‌آید ایندکس ایجاد می‌کنند.

نتیجه‌ی این رویکرد:

  • افزایش شدید حجم ایندکس‌ها

  • کند شدن Insert و Update

  • Fragmentation بالا

  • هزینه‌ی نگهداری بیشتر

  • بدون بهبود واقعی در Performance

ایندکس زیاد، الزاماً ایندکس مؤثر نیست.
در واقع، در بسیاری از سیستم‌ها، تعداد بالای ایندکس نشانه‌ی ضعف تحلیل است، نه بلوغ فنی.

Low Selectivity فقط مشکل ستون‌های Boolean نیست

برخلاف تصور رایج، Low Selectivity فقط به ستون‌های True/False محدود نمی‌شود.
ستون‌های زیر نیز اغلب Selectivity پایینی دارند:

  • Status (Pending / Approved / Rejected)

  • Gender

  • Type

  • Category با تعداد محدود

  • Flagهای منطقی و کنترلی

اگر یک ستون فقط چند مقدار پرتکرار دارد، ایندکس روی آن به‌تنهایی معمولاً ارزش ندارد، حتی اگر در WHERE زیاد استفاده شود.

نقش حیاتی Statistics در تشدید یا پنهان‌سازی Low Selectivity

Statistics به Optimizer می‌گویند:

  • هر مقدار چند بار تکرار شده

  • توزیع داده چگونه است

  • تخمین Cardinality چگونه باید انجام شود

وقتی Statistics قدیمی باشند یا توزیع داده تغییر کرده باشد، Optimizer تصمیم‌های ناپایدار می‌گیرد.
در این حالت، یک Query گاهی Seek می‌زند و گاهی Scan، بدون اینکه کد تغییر کرده باشد.

ترکیب خطرناک:

Low Selectivity + Statistics ضعیف = Performance غیرقابل پیش‌بینی

در چنین شرایطی، تیم‌ها معمولاً به‌اشتباه سراغ Hint، Recompile یا Force Plan می‌روند، در حالی که ریشه‌ی مشکل جای دیگری است.

Composite Index اولین راه فرار حرفه‌ای از Low Selectivity

یکی از مؤثرترین راهکارها، ترکیب ستون کم‌انتخاب‌پذیر با ستون پرانتخاب است.

به‌جای این ایندکس ساده و کم‌اثر:

CREATE INDEX IX_Orders_IsActive
ON Orders(IsActive)

از این ساختار استفاده می‌شود:

CREATE INDEX IX_Orders_IsActive_CreateDate
ON Orders(IsActive, CreateDate)

در این طراحی:

  • IsActive دامنه‌ی اولیه را محدود می‌کند

  • CreateDate Selectivity واقعی ایجاد می‌کند

  • Optimizer دلیل منطقی برای Seek پیدا می‌کند

نکته‌ی حیاتی اینجاست:
ترتیب ستون‌ها در Composite Index کاملاً تعیین‌کننده است.

Filtered Index پاسخ هدفمند به داده‌های پرتکرار

در بسیاری از سناریوهای واقعی، فقط بخشی از داده‌ها اهمیت عملیاتی دارند.
در اینجا، Filtered Index یکی از هوشمندانه‌ترین ابزارهاست.

مثال:

CREATE INDEX IX_Orders_Active
ON Orders(CreateDate)
WHERE IsActive = ۱

مزایا:

  • حجم ایندکس کوچک می‌ماند

  • Selectivity واقعی ایجاد می‌شود

  • هزینه‌ی Insert و Update کاهش می‌یابد

  • Queryهای هدفمند سریع‌تر می‌شوند

Filtered Index زمانی می‌درخشد که Query Pattern مشخص و پایدار باشد.

Low Selectivity و Key Lookupهای مخرب

حتی در شرایطی که Optimizer از ایندکس استفاده می‌کند، Low Selectivity می‌تواند باعث فاجعه‌ی پنهان شود: Key Lookupهای انبوه.

سناریوی رایج:

  • Index Seek انجام می‌شود

  • اما هزاران Lookup برای ستون‌های دیگر اجرا می‌شود

  • IO و CPU به‌شدت افزایش پیدا می‌کند

در این حالت، ایندکس «استفاده شده»، اما نتیجه‌ی نهایی بدتر از Scan است.

راه‌حل حرفه‌ای:

  • طراحی Covering Index

  • یا بازنگری ساختار Query و Projection

چرا برخی ایندکس‌ها فقط روی کاغذ خوب‌اند؟

در بسیاری از پروژه‌ها، ایندکس‌ها:

  • بدون سناریوی واقعی Query ساخته می‌شوند

  • بدون بررسی Execution Plan

  • بدون تحلیل حجم و توزیع داده

این ایندکس‌ها:

  • در مستندات وجود دارند

  • اما در Execution Plan دیده نمی‌شوند

Low Selectivity معمولاً دلیل اصلی این شکاف بین طراحی و واقعیت است.

نشانه‌های سازمانی درگیری با Low Selectivity

اگر در سیستم خود این نشانه‌ها را مشاهده می‌کنید، احتمالاً مشکل از Low Selectivity است:

  • ایندکس وجود دارد اما Scan غالب است

  • CPU بالا بدون Query پیچیده

  • اختلاف شدید Performance بین محیط‌ها

  • ایندکس‌های زیاد با Usage نزدیک صفر

  • Query Store پر از Planهای ناپایدار

این‌ها خطای SQL Server نیستند؛ خطای طراحی هستند.

تأثیر Low Selectivity در OLTP و BI

در سیستم‌های OLTP:

  • Lock بیشتر می‌شود

  • Throughput کاهش پیدا می‌کند

  • Latency افزایش می‌یابد

در سیستم‌های BI و تحلیلی:

  • Scanهای سنگین ایجاد می‌شود

  • فشار روی TempDB بالا می‌رود

  • Refresh گزارش‌ها کند می‌شود

هر دو سناریو، ریشه یکسان است: ایندکس بدون Selectivity.

رویکرد DBA بالغ به طراحی ایندکس

یک DBA حرفه‌ای این‌گونه فکر می‌کند:

  • این ایندکس دقیقاً کدام Query را بهبود می‌دهد؟

  • Selectivity واقعی کجاست؟

  • Composite یا Filtered کدام منطقی‌تر است؟

  • هزینه‌ی Write چقدر افزایش می‌یابد؟

ایندکس ابزار است، نه هدف.

چک‌لیست عملی تشخیص Low Selectivity

  • بررسی Distribution در Statistics

  • تحلیل Execution Plan قبل و بعد از ایندکس

  • بررسی sys.dm_db_index_usage_stats

  • مقایسه‌ی Scan و Seek

  • تحلیل Key Lookupها

بدون این مراحل، ایندکس‌سازی بیشتر شبیه حدس‌زدن است تا مهندسی.

جمع‌بندی

Low Selectivity دشمن خاموش Performance است.
ایندکس‌هایی که بدون درک توزیع داده ساخته می‌شوند، نه‌تنها کمکی نمی‌کنند، بلکه هزینه‌ی سیستم را بالا می‌برند.

Performance پایدار زمانی ایجاد می‌شود که:

  • Selectivity فهمیده شود

  • ایندکس هدفمند طراحی شود

  • Query و داده با هم دیده شوند

ایندکس زیاد، نشانه‌ی بلوغ نیست.
ایندکس مؤثر، نشانه‌ی فهم عمیق است.

پرسش‌های متداول (FAQ)

۱. آیا Low Selectivity همیشه به این معناست که نباید ایندکس بسازیم؟

خیر.
Low Selectivity به این معنا نیست که ایندکس «غلط» است، بلکه یعنی ایندکس به‌تنهایی تصمیم‌ساز نیست.
در بسیاری از سناریوها، ستون‌های با Selectivity پایین وقتی در کنار ستون‌های پرانتخاب‌پذیر قرار می‌گیرند، به بخشی از یک Composite Index مؤثر تبدیل می‌شوند.

مشکل زمانی ایجاد می‌شود که یک ستون کم‌انتخاب‌پذیر به‌عنوان ستون اصلی و مستقل ایندکس استفاده شود، بدون درنظرگرفتن الگوی واقعی Query.

۲.چرا SQL Server گاهی با وجود Low Selectivity باز هم از Index Seek استفاده می‌کند؟

این رفتار معمولاً به یکی از دلایل زیر رخ می‌دهد:

  • Statistics قدیمی یا ناقص هستند

  • Cardinality Estimation اشتباه انجام شده

  • Parameter Sniffing باعث تخمین نادرست شده است

  • حجم داده در لحظه اجرا کمتر از حالت عادی بوده

به همین دلیل است که گاهی یک Query Seek می‌زند و چند ساعت بعد همان Query Scan می‌شود.
این ناپایداری نشانه‌ی «هوشمندی» نیست؛ نشانه‌ی عدم قطعیت Optimizer به‌دلیل Selectivity پایین است.

۳.آیا استفاده از Index Hint می‌تواند مشکل Low Selectivity را حل کند؟

در اغلب موارد، خیر.
Index Hint فقط Optimizer را مجبور به استفاده از یک ایندکس می‌کند، اما منطق اقتصادی پشت تصمیم را اصلاح نمی‌کند.

نتیجه‌ی رایج:

  • افزایش IO

  • Key Lookupهای انفجاری

  • Performance بدتر در حجم داده‌ی بالاتر

Index Hint باید آخرین ابزار باشد، نه راه‌حل پیش‌فرض.
اگر مجبور به Hint هستید، معمولاً طراحی ایندکس یا Query ایراد دارد.

۴.Low Selectivity چه تفاوتی با Over-Indexing دارد؟

این دو مفهوم به‌هم مرتبط‌اند، اما یکسان نیستند.

  • Low Selectivity به کیفیت داده و توان فیلتر ستون اشاره دارد

  • Over-Indexing به تعداد زیاد ایندکس‌های کم‌اثر یا بلااستفاده

در عمل، Low Selectivity یکی از دلایل اصلی Over-Indexing است؛
زیرا تیم‌ها برای جبران Performance، ایندکس‌های بیشتری می‌سازند، بدون اینکه Selectivity واقعی ایجاد شود.

۵.آیا Filtered Index همیشه بهترین راه‌حل برای Low Selectivity است؟

خیر، اما در سناریوهای درست، یکی از بهترین گزینه‌هاست.
Filtered Index زمانی بیشترین ارزش را دارد که:

  • Query Pattern مشخص و پایدار باشد

  • فقط بخشی از داده‌ها دائماً مورد استفاده باشند

  • شرط Filter تغییر نکند

اگر شرط WHERE دائماً تغییر می‌کند یا پارامترمحور است، Filtered Index ممکن است بی‌اثر یا حتی گمراه‌کننده شود.

۶.چگونه Selectivity واقعی یک ستون را قبل از ساخت ایندکس ارزیابی کنیم؟

روش‌های عملی شامل:

  • بررسی Histogram در Statistics

  • محاسبه‌ی نسبت Distinct Values به Total Rows

  • تحلیل Queryهای پرتکرار در Query Store

  • مشاهده‌ی Execution Planهای واقعی، نه تخمینی

تصمیم ایندکس‌سازی باید مبتنی بر داده‌ی واقعی اجرا باشد، نه حدس.

۷.آیا Low Selectivity در دیتابیس‌های کوچک هم اهمیت دارد؟

در دیتابیس‌های کوچک، اثر آن کمتر دیده می‌شود، اما حذف نمی‌شود.
مشکل اصلی اینجاست که:

ایندکس بد در دیتابیس کوچک →
فاجعه در دیتابیس بزرگ آینده

طراحی ایندکس باید از ابتدا با نگاه مقیاس‌پذیر انجام شود، نه بر اساس حجم فعلی داده.

۸.نشانه‌ی قطعی اینکه مشکل Performance از Low Selectivity است چیست؟

هیچ نشانه‌ی واحدی قطعی نیست، اما ترکیب این موارد هشدار جدی است:

  • Scan روی جدول‌های بزرگ با وجود ایندکس

  • Usage نزدیک صفر برای ایندکس‌های به‌ظاهر مهم

  • Planهای ناپایدار در Query Store

  • Key Lookupهای پرتعداد با Seek ظاهراً موفق

در این حالت، تحلیل Selectivity باید اولین اقدام باشد.

۹.DBA حرفه‌ای چه زمانی تصمیم می‌گیرد ایندکس را حذف کند؟

زمانی که:

  • Selectivity ستون تغییر کرده

  • الگوی Query عوض شده

  • ایندکس هزینه Write بالایی دارد

  • Usage واقعی نزدیک صفر است

حذف ایندکس نشانه‌ی ضعف نیست؛
نشانه‌ی تصمیم‌گیری آگاهانه است.

چه زمانی ایندکس شما واقعاً ارزش DBA دارد؟

وقتی بدانید هر ایندکس دقیقاً کدام Query را بهبود می‌دهد و کدام فقط منابع سیستم را مصرف می‌کند.
در بسیاری از سازمان‌ها، ایندکس‌ها سال‌ها بدون بازبینی باقی می‌مانند، در حالی که حجم داده، الگوی Query و نیازهای کسب‌وکار به‌طور کامل تغییر کرده است. نتیجه، دیتابیسی است پر از ایندکس‌هایی که روی کاغذ منطقی‌اند، اما در عمل تصمیم‌ساز نیستند.

تیم لاندا با Audit تخصصی ایندکس‌ها، تحلیل دقیق Selectivity، بررسی Execution Planهای واقعی و بازطراحی هدفمند ساختار ایندکس کمک می‌کند Performance پایدار و قابل اتکا ایجاد شود، نه صرفاً ایندکس بیشتر و هزینه‌ی بالاتر.

اگر می‌خواهید بدانید:

  • کدام ایندکس‌ها واقعاً استفاده می‌شوند

  • کدام ایندکس‌ها فقط Write Cost تولید می‌کنند

  • و کجا Performance قربانی Low Selectivity شده است

اکنون زمان بررسی تخصصی فرا رسیده است.
تصمیم‌گیری آگاهانه درباره ایندکس‌ها، همان نقطه‌ای است که DBA حرفه‌ای از ایندکس‌سازی تجربی جدا می‌شود.

برای بررسی بیشتر  با کارشناسان لاندا تماس  بگیرید.

نظری داده نشده

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *