مدیریت و حذف ایندکس های Unused یا تکراری (Redundant) یکی از وظایف حیاتی DBA است؛ چرا که ایندکس های B-Tree سنتی سربار ذخیره سازی، مصرف حافظه (Buffer Pool) و کاهش کارایی تراکنش های نوشتن (DML) را به همراه دارند. با این حال، تکیه مطلق بر آمارهای کمیِ DMVها برای حذف ایندکس ها می تواند کارایی کل سیستم را با چالش جدی مواجه کند.
ملاحظات کیفی و فنی که باید پیش از حذف، اصلاح یا ادغام ایندکس ها مد نظر قرار گیرند، به شرح زیر است:
۱. چالش تحلیل تک بعدی DMVها (نرخ خواندن پایین به نوشتن بالا): صرفِ بالا بودن آمار نوشتن (Writes) نسبت به خواندن (Reads) در sys.dm_db_index_usage_stats دلیلی بر بیهوده بودن ایندکس نیست:
- کوئری های بحرانی اما کم تکرار: برخی ایندکس ها ممکن است فقط برای گزارش های دوره ای (شبانه، هفتگی، ماهانه) یا توسط مدیران ارشد اجرا شوند. تبدیل یک Table/Index Scan به یک Index Seek کارآمد در این سناریوها، ارزش سربار نوشتن های مداوم را دارد.
- تفاوت رفتار در Availability Group (AG): الگوهای دسترسی روی سرور Primary و Secondary کاملاً متفاوت است. برای بررسی دقیق، باید وضعیت Seek/Scan را روی تمامی نسخه های فرعی (Replicaها) نیز پایش کرد.
- دوره آماری ناقص: داده های DMVها با ری استارت شدن سرویس SQL Server یا تغییرات پیکربندی (Configuration) بازنشانی می شوند. لذا اطلاعات موجود لزوماً کل چرخه ی کسب وکار را پوشش نمی دهد. برای شناسایی کامل، باید sys.indexes را با sys.dm_db_index_usage_stats به صورت LEFT OUTER JOIN ترکیب کرد تا ایندکس هایی که اصلاً ثبت نشده اند نیز ردیابی شوند.
۲. تشخیص نادرستِ ایندکس های یکسان (Redundancy): یکسان بودن ستون های کلیدی (Key Columns) به معنای هم پوشانی کامل یا بیهودگی یکی از آن ها نیست:
- ترتیب ستون ها: ایندکس روی (A, B) با ایندکس روی (B, A) به دلیل ساختار درختی B-Tree کاملاً متفاوت عمل می کند و کارکرد یکسانی برای Query Optimizer ندارد.
- Filtered Indexes: دو ایندکس با کلیدهای یکسان اما شرط های WHERE متفاوت (مثلاً تفکیک داده های آرشیو از جاری) کاملاً مجزا و کاربردی هستند.
- Included Columns: تفاوت در بخش INCLUDE می تواند یک ایندکس را برای کوئری های گزارش گیری عریض و دیگری را برای کوئری های OLTP سبک بهینه کند.
- ضعف ابزارهای قدیمی: ابزار سنتی sp_helpindex اطلاعات مربوط به فیلترها و ستون های Included را نشان نمی دهد و ممکن است دو ایندکس متفاوت را یکسان جلوه دهد. استفاده از ابزارهای مدرن تر نظیر sp_BlitzIndex توصیه می شود.
۳. استراتژی های بهینه سازی و اصلاح ساختار: فرآیند پاکسازی صرفاً حذف کردن نیست، بلکه اصلاح ساختار را نیز شامل می شود:
- Uniqueness: اگر یک ایندکس به طور منطقی یکتاست (مثلاً ستون کلید اصلی را در ابتدای کلیدهای خود دارد)، تعریف صریح آن به عنوان UNIQUE به بهینه ساز کوئری کمک می کند تا Planهای بهتری تولید کرده و نیاز به عملیات اضافی مثل DISTINCT را از بین ببرد.
- رفع عملیات Sort اضافه: برای کوئری هایی که نیاز به مرتب سازی دارند، قرار دادن ستون دوم در بخش Key به جای Include (مثال: تغییر از (FK) INCLUDE (Date) به (FK, Date)) بدون افزایش محسوس حجم ایندکس، عملیات سنگین Sort در Execution Plan را حذف می کند.
- ریسک های تغییر نام: تغییر نام ایندکس های غیراستاندارد یا آزمایشی باید با احتیاط انجام شود، زیرا ممکن است ایندکس به طور صریح در Query Hintها، اسکریپت های Deployment یا وظایف نگهداری (Maintenance) هاردکد شده باشد.
۴. متدولوژی اقدام:
- بررسی سوابق و مستندات: پیش از حذف، علت ایجاد ایندکس را در کدهای سورس کنترل (Git)، تیکت های پشتیبانی و ارتباطات درون تیمی جستجو کنید.
- شبیه سازی و تست: تغییرات را ابتدا در محیط Staging/Test اعمال کنید. اگرچه شبیه سازی کاملِ لودِ پروداکشن دشوار است، اما تأثیر حذف یا تغییر ایندکس بر روی سنگین ترین کوئری های سیستم (از نظر IO/CPU) باید به دقت ارزیابی شود.
سید حامد واحدی
15 مرداد 1405