خانه/ وبلاگ/ ایندکس در SQL Server چیست و چرا Query را سریع می‌کند؟ (آموزش مبتدی)
آموزش SQL

ایندکس در SQL Server چیست و چرا Query را سریع می‌کند؟ (آموزش مبتدی)

آموزش SQL ۵ آبان ۱۴۰۵ 11 دقیقه مطالعه

فرض کن در یک کتاب هزار صفحه‌ای دنبال کلمه‌ی «تراکنش» می‌گردی. بدون فهرست انتهای کتاب باید همه‌ی صفحه‌ها را ورق بزنی؛ با فهرست مستقیم به صفحه‌ی درست می‌روی. ایندکس (Index) در پایگاه‌داده دقیقاً همین فهرست است.

ایندکس سرعت خواندن را زیاد می‌کند، اما هزینه‌اش کندتر شدن نوشتن و مصرف فضای بیشتر است.

بدون ایندکس چه می‌شود؟

وقتی روی ستونی ایندکس نیست، SQL Server برای WHERE Email = 'a@b.com' مجبور است همه‌ی ردیف‌ها را بخواند (Table Scan). با میلیون‌ها ردیف این کار ثانیه‌ها طول می‌کشد. با ایندکس، جستجو در یک ساختار درختی (B-Tree) انجام می‌شود و با چند جهش به ردیف می‌رسد (Index Seek).

RootIntermediateIntermediateIntermediate LeafLeafLeafLeafLeafLeaf
ایندکس به‌صورت B-Tree: جستجو از ریشه شروع می‌شود و با چند سطح به برگ (داده یا اشاره‌گر به داده) می‌رسد.

ایندکس خوشه‌ای (Clustered)

ایندکس خوشه‌ای خودِ ردیف‌های جدول را بر اساس کلید مرتب ذخیره می‌کند؛ مثل دفترچه‌ی تلفنی که بر اساس نام مرتب است. به همین دلیل هر جدول فقط یک ایندکس خوشه‌ای دارد. به‌طور پیش‌فرض PRIMARY KEY یک ایندکس خوشه‌ای می‌سازد:

sql
CREATE TABLE Orders (
  OrderId    INT IDENTITY PRIMARY KEY,   -- Clustered Index پیش‌فرض
  CustomerId INT NOT NULL,
  OrderDate  DATE NOT NULL,
  Amount     DECIMAL(12,2) NOT NULL
);

ایندکس غیرخوشه‌ای (NonClustered)

ایندکس غیرخوشه‌ای ساختاری جداگانه است که مقدار ستون و اشاره‌گر به ردیف اصلی را نگه می‌دارد؛ مثل فهرست انتهای کتاب. هر جدول تا ۹۹۹ ایندکس NonClustered می‌تواند داشته باشد:

sql
-- جستجوی سفارش‌های یک مشتری را سریع می‌کند
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId
ON Orders (CustomerId);

SELECT OrderId, Amount FROM Orders WHERE CustomerId = 42;

ایندکس ترکیبی و ترتیب ستون‌ها

وقتی شرط چند ستون دارد، یک ایندکس ترکیبی مناسب‌تر است. ترتیب ستون‌ها مهم است؛ ایندکس برای پیشوند چپ کار می‌کند:

sql
CREATE INDEX IX_Orders_Customer_Date ON Orders (CustomerId, OrderDate);

-- این پرس‌وجوها از ایندکس استفاده می‌کنند:
SELECT * FROM Orders WHERE CustomerId = 42;
SELECT * FROM Orders WHERE CustomerId = 42 AND OrderDate >= '2026-01-01';

-- این یکی از ایندکس به‌خوبی استفاده نمی‌کند (ستون اول در شرط نیست):
SELECT * FROM Orders WHERE OrderDate >= '2026-01-01';

INCLUDE و ایندکس پوششی

اگر Query فقط چند ستون می‌خواهد، می‌توان آن‌ها را در برگ‌های ایندکس با INCLUDE نگه داشت تا SQL Server اصلاً به جدول اصلی مراجعه نکند (حذف Key Lookup):

sql
CREATE INDEX IX_Orders_Customer_Cover
ON Orders (CustomerId)
INCLUDE (Amount, OrderDate);

Seek یا Scan؟ با Execution Plan بخوان

عملگریعنیوضعیت
Index Seekمستقیم به ردیف‌های موردنیاز رفتهعالی
Index Scanکل ایندکس را خواندهبسته به حجم؛ بررسی کن
Table Scanکل جدول را خواندهمعمولاً نیاز به ایندکس
Key Lookupبرای ستون‌های ناقص به جدول اصلی مراجعه کردهبا INCLUDE قابل‌حذف

در SSMS با Ctrl+M نمایش Actual Execution Plan را روشن کن و Query را اجرا کن. جزئیات بیشتر در پیدا کردن Queryهای کند.

اشتباه‌هایی که ایندکس را بی‌اثر می‌کنند

  • تابع روی ستون: WHERE YEAR(OrderDate) = 2026 ایندکس را بی‌اثر می‌کند؛ به‌صورت بازه بنویس (OrderDate >= '2026-01-01' AND OrderDate < '2027-01-01').
  • LIKE با علامت ابتدایی: LIKE '%abc' نمی‌تواند Seek کند؛ LIKE 'abc%' می‌تواند.
  • تبدیل نوع ضمنی: مقایسه‌ی ستون VARCHAR با مقدار NVARCHAR می‌تواند ایندکس را کنار بگذارد.
  • ایندکس روی ستون‌های کم‌تنوع (مثل جنسیت با دو مقدار) معمولاً فایده ندارد.
  • ایندکس‌های زیاد و تکراری نوشتن را کند می‌کنند.

قواعد سرانگشتی

  • روی ستون‌های PRIMARY KEY و کلیدهای خارجی پرمصرف ایندکس داشته باش.
  • ستون‌های پرتکرار در WHERE، JOIN و ORDER BY کاندید ایندکس هستند.
  • بعد از ساخت ایندکس، Execution Plan را دوباره بررسی کن و اثرش را اندازه بگیر.
  • ایندکس‌های بلااستفاده را با DMVهایی مثل sys.dm_db_index_usage_stats پیدا و حذف کن.

برای فهم عمیق‌تر، درس‌های ایندکس خوشه‌ای، غیرخوشه‌ای و Execution Plan را بخوان.

سوالات متداول درباره‌ی این موضوع

آیا هر چه ایندکس بیشتر باشد بهتر است؟

نه. هر ایندکس فضای دیسک می‌گیرد و هر INSERT/UPDATE/DELETE باید همه‌ی ایندکس‌های جدول را هم به‌روز کند. فقط برای ستون‌هایی که زیاد در WHERE، JOIN و ORDER BY استفاده می‌شوند ایندکس بساز.

تفاوت Clustered و NonClustered چیست؟

ایندکس Clustered ترتیب فیزیکی ذخیره‌ی خود ردیف‌ها را تعیین می‌کند و فقط یکی در هر جدول است (معمولاً روی Primary Key). NonClustered یک ساختار جداگانه با اشاره‌گر به ردیف‌هاست و می‌توان چندتا داشت.

چطور بفهمم Query از ایندکس استفاده می‌کند؟

Execution Plan را در SSMS ببین (Ctrl+M و اجرای Query). اگر عملگر Index Seek باشد از ایندکس به‌خوبی استفاده شده؛ Table Scan یا Index Scan یعنی کل داده خوانده شده است.

مصطفی موسویسازنده و نویسنده‌ی SQLFarsi. اگر اشتباهی در مقاله دیدی یا پیشنهادی داری، از طریق mousavi.dev خبر بده.

می‌خوای SQL را از پایه و با تمرین یاد بگیری؟

دوره‌ی رایگان SQLFarsi را با Playground و پروژه‌های واقعی دنبال کن.

شروع یادگیری