ایندکس در SQL Server چیست و چرا Query را سریع میکند؟ (آموزش مبتدی)
فرض کن در یک کتاب هزار صفحهای دنبال کلمهی «تراکنش» میگردی. بدون فهرست انتهای کتاب باید همهی صفحهها را ورق بزنی؛ با فهرست مستقیم به صفحهی درست میروی. ایندکس (Index) در پایگاهداده دقیقاً همین فهرست است.
بدون ایندکس چه میشود؟
وقتی روی ستونی ایندکس نیست، SQL Server برای WHERE Email = 'a@b.com' مجبور است همهی ردیفها را بخواند (Table Scan). با میلیونها ردیف این کار ثانیهها طول میکشد. با ایندکس، جستجو در یک ساختار درختی (B-Tree) انجام میشود و با چند جهش به ردیف میرسد (Index Seek).
ایندکس خوشهای (Clustered)
ایندکس خوشهای خودِ ردیفهای جدول را بر اساس کلید مرتب ذخیره میکند؛ مثل دفترچهی تلفنی که بر اساس نام مرتب است. به همین دلیل هر جدول فقط یک ایندکس خوشهای دارد. بهطور پیشفرض PRIMARY KEY یک ایندکس خوشهای میسازد:
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 میتواند داشته باشد:
-- جستجوی سفارشهای یک مشتری را سریع میکند CREATE NONCLUSTERED INDEX IX_Orders_CustomerId ON Orders (CustomerId); SELECT OrderId, Amount FROM Orders WHERE CustomerId = 42;
ایندکس ترکیبی و ترتیب ستونها
وقتی شرط چند ستون دارد، یک ایندکس ترکیبی مناسبتر است. ترتیب ستونها مهم است؛ ایندکس برای پیشوند چپ کار میکند:
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):
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 یعنی کل داده خوانده شده است.
میخوای SQL را از پایه و با تمرین یاد بگیری؟
دورهی رایگان SQLFarsi را با Playground و پروژههای واقعی دنبال کن.
شروع یادگیری