آموزش CREATE CLUSTERED INDEX در SQL Server؛ ساخت ایندکس خوشه‌ای با ۱۰ مثال عملی

آموزش CREATE CLUSTERED INDEX در SQL Server؛ ساخت ایندکس خوشه‌ای

توسط admin | گروه SQL Server | 1405/04/31

نظرات 0

آموزش CREATE CLUSTERED INDEX در SQL Server؛ ساخت ایندکس خوشه‌ای

مقدمه

CREATE CLUSTERED INDEX یکی از دستورهای مهم طراحی و بهینه‌سازی در Microsoft SQL Server است. هدف آن تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است. تعریف درست می‌تواند خواندن منطقی، CPU و زمان پاسخ را کاهش دهد، اما تعریف نامناسب فضای ذخیره‌سازی و هزینه INSERT، UPDATE و DELETE را بالا می‌برد.

در این آموزش از مفاهیم پایه شروع می‌کنیم و سپس Syntax، پیش‌نیازها، پارامترها، ده مثال مستقل، نتیجه مورد انتظار، خطاهای رایج و روش سنجش کارایی را بررسی می‌کنیم. همه تصمیم‌ها باید با داده و Query واقعی اعتبارسنجی شوند، زیرا نسخه واحدی برای همه جدول‌ها وجود ندارد.

برای مشاهده نقشه کامل خانواده ایندکس‌ها، ابتدا راهنمای جامع دستورات ساخت ایندکس در SQL Server را مطالعه کنید. این صفحه جایگاه ساخت ایندکس خوشه‌ای را در کنار Rowstore، Columnstore و ایندکس‌های تخصصی نشان می‌دهد.

تعریف و کاربرد CREATE CLUSTERED INDEX

ساخت ایندکس خوشه‌ای در گروه ایندکس‌های Rowstore قرار می‌گیرد. تعریف ایندکس یک تصمیم فیزیکی درباره نحوه دسترسی به داده است؛ موتور پایگاه داده همچنان نتیجه منطقی Query را یکسان نگه می‌دارد، اما مسیر رسیدن به نتیجه می‌تواند از Scan پرهزینه به Seek یا پردازش ستونی هدفمند تغییر کند.

مهم‌ترین کاربرد این دستور، تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است. پیش از اجرا باید مالکیت Schema، مجوز ALTER روی جدول، فضای کافی، سلامت داده و سازگاری گزینه‌ها با نسخه سرور بررسی شود. نام‌گذاری یکنواخت نیز عیب‌یابی، Deployment و نگهداری آینده را ساده‌تر می‌کند.

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

نحو عمومی دستور

CREATE CLUSTERED INDEX IX_CREATE_CLUSTERED_INDEX
    ON dbo.TableName(KeyColumn ASC)
    WITH (FILLFACTOR = 95, SORT_IN_TEMPDB = ON);
    

اجزای مهم تعریف

جزءنقشپرسش کنترلی
نام ایندکسشناسه قابل نگهداری و استقرارآیا الگوی نام‌گذاری تیم رعایت شده است؟
جدول و Schemaهدف فیزیکی ساختارآیا محیط و Schema دقیق انتخاب شده‌اند؟
ستون کلیدیتعیین مسیر جست‌وجو یا سازمان‌دهیآیا ترتیب با Predicate و Sort هماهنگ است؟
گزینه‌های WITHکنترل ساخت، قفل، فضا و نگهداریآیا نسخه و Edition از گزینه پشتیبانی می‌کند؟
اعتبارسنجیاثبات اثر پس از ساختآیا Plan و IO قبل و بعد ثبت شده‌اند؟

پیش‌نیازها و طراحی قبل از اجرا

ابتدا Query Store، Extended Events یا ابزار مانیتورینگ را برای یافتن Queryهای پرهزینه بررسی کنید. تعداد اجرا و اثر تجمعی مهم‌تر از کندی یک اجرای نادر است. سپس Actual Execution Plan را همراه با پارامتر واقعی ذخیره کنید تا مشکل Scan، Lookup، Sort، Hash Spill یا تخمین اشتباه قابل مشاهده باشد.

توزیع داده و Selectivity ستون‌ها را با Statistics و Queryهای شمارشی بررسی کنید. ستونی با چند مقدار تکراری همیشه کلید خوبی نیست، مگر آنکه با فیلتر، ستون دوم یا ساختار تخصصی ترکیب شود. نوع داده کلید نیز بر اندازه صفحه، Fan-out و هزینه حافظه اثر مستقیم دارد.

در مرحله استقرار، مدت ساخت، رشد Transaction Log، فضای آزاد Data File و TempDB، احتمال Blocking و امکان Online Operation را برآورد کنید. برای محیط حساس، اسکریپت بازگشت و معیار توقف باید پیش از شروع تأیید شده باشد.

  • ثبت Query، پارامتر، Plan و شاخص‌های پایه پیش از تغییر
  • بررسی ایندکس‌های موجود و حذف هم‌پوشانی غیرضروری
  • کنترل نوع داده، طول کلید و توزیع مقادیر
  • توجه ویژه به انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی
  • آزمون هم‌زمانی خواندن و نوشتن در محیط مشابه تولید
  • ثبت برنامه استقرار، پایش و بازگشت

مثال‌های عملی

مثال 1: ساخت پایه روی ستون پرتکرار با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE1', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE1;
    
    CREATE TABLE dbo.DemoClusteredIndexE1
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE1
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E1
        ON dbo.DemoClusteredIndexE1(RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE1')
      AND name = N'IX_DemoClusteredIndex_E1';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE1
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E1CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: این الگو نقطه شروع است؛ در سامانه واقعی باید انتخاب ستون با Execution Plan و آمار مصرف تأیید شود. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 2: کلید مرکب برای جست‌وجوی چندشرطی با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE2', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE2;
    
    CREATE TABLE dbo.DemoClusteredIndexE2
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE2
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E2
        ON dbo.DemoClusteredIndexE2(CustomerID, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE2')
      AND name = N'IX_DemoClusteredIndex_E2';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE2
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E2CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: ستون سمت چپ کلید نقش تعیین‌کننده دارد و تغییر ترتیب ستون‌ها می‌تواند شکل Seek را عوض کند. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 3: پشتیبانی از مرتب‌سازی نزولی با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE3', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE3;
    
    CREATE TABLE dbo.DemoClusteredIndexE3
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE3
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E3
        ON dbo.DemoClusteredIndexE3(OrderDate DESC, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE3')
      AND name = N'IX_DemoClusteredIndex_E3';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE3
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E3CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: جهت کلید زمانی مهم‌تر می‌شود که Query ترکیبی از چند ستون با جهت‌های متفاوت داشته باشد. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 4: استفاده در شرط و اتصال جدول‌ها با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE4', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE4;
    
    CREATE TABLE dbo.DemoClusteredIndexE4
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE4
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E4
        ON dbo.DemoClusteredIndexE4(Status, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE4')
      AND name = N'IX_DemoClusteredIndex_E4';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE4
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E4CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: وجود ایندکس تضمین استفاده از آن نیست؛ Optimizer بر پایه آمار، تعداد ردیف و هزینه تخمینی تصمیم می‌گیرد. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 5: تنظیم گزینه‌های ساخت و نگهداری با CREATE CLUSTERED INDEX

یکی از گزینه‌های متداول ساخت ایندکس مانند FILLFACTOR، SORT_IN_TEMPDB یا فشرده‌سازی در یک سناریوی کنترل‌شده نمایش داده می‌شود. در این مثال، هدف عملی تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است.

IF OBJECT_ID(N'dbo.DemoClusteredIndexE5', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE5;
    
    CREATE TABLE dbo.DemoClusteredIndexE5
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE5
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E5
        ON dbo.DemoClusteredIndexE5(RowID) WITH (FILLFACTOR = 95, SORT_IN_TEMPDB = ON);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE5')
      AND name = N'IX_DemoClusteredIndex_E5';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE5
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E5CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: هر گزینه هزینه و پیش‌نیاز خود را دارد؛ مقدار مناسب باید با نسخه SQL Server، Edition و الگوی بار واقعی آزموده شود. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 6: رفتار با NULL و داده‌های اختیاری با CREATE CLUSTERED INDEX

داده‌ای دارای مقدار NULL وارد می‌شود تا اثر آن بر تعریف، انتخاب‌پذیری و نتیجه Query روشن شود. در این مثال، هدف عملی تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است.

IF OBJECT_ID(N'dbo.DemoClusteredIndexE6', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE6;
    
    CREATE TABLE dbo.DemoClusteredIndexE6
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE6
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E6
        ON dbo.DemoClusteredIndexE6(Status, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE6')
      AND name = N'IX_DemoClusteredIndex_E6';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE6
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E6CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: NULL مقدار عادی نیست و قواعد یکتایی، فیلتر و برآورد Cardinality را باید آگاهانه بررسی کرد. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 7: سناریوی مرزی با دامنه تاریخی با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE7', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE7;
    
    CREATE TABLE dbo.DemoClusteredIndexE7
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE7
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E7
        ON dbo.DemoClusteredIndexE7(OrderDate, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE7')
      AND name = N'IX_DemoClusteredIndex_E7';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE7
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E7CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: در بازه‌های بسیار بزرگ، به‌روز بودن Statistics و هماهنگی نوع پارامتر با نوع ستون اهمیت ویژه دارد. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 8: گزارش سازمانی و ستون‌های خروجی با CREATE CLUSTERED INDEX

نمونه گزارش فروش یا عملیات با چند ستون خروجی ارائه می‌شود تا مرز میان کلید جست‌وجو و داده موردنیاز نمایش مشخص شود. در این مثال، هدف عملی تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است.

IF OBJECT_ID(N'dbo.DemoClusteredIndexE8', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE8;
    
    CREATE TABLE dbo.DemoClusteredIndexE8
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE8
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E8
        ON dbo.DemoClusteredIndexE8(CustomerID, OrderDate, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE8')
      AND name = N'IX_DemoClusteredIndex_E8';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE8
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E8CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: هدف کاهش خواندن صفحه و حذف عملیات اضافه است، نه افزودن همه ستون‌های جدول به هر ایندکس. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 9: روش اشتباه و نسخه اصلاح‌شده با CREATE CLUSTERED INDEX

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

IF OBJECT_ID(N'dbo.DemoClusteredIndexE9', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE9;
    
    CREATE TABLE dbo.DemoClusteredIndexE9
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE9
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    -- روش اشتباه: ساخت ایندکس بسیار عریض بدون بررسی الگوی Query
    -- نسخه اصلاح‌شده و هدفمند در ادامه اجرا می‌شود.
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E9
        ON dbo.DemoClusteredIndexE9(CustomerID, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE9')
      AND name = N'IX_DemoClusteredIndex_E9';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE9
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E9CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: بازبینی نام، نوع داده، ترتیب ستون و قابلیت‌های مجاز پیش از اجرای DDL از خطا و Downtime جلوگیری می‌کند. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

مثال 10: کنترل نتیجه و سنجش کارایی با CREATE CLUSTERED INDEX

پس از ساخت، نمای سیستمی و یک Query نمونه برای کنترل نوع ایندکس و آماده‌سازی ارزیابی کارایی استفاده می‌شوند. در این مثال، هدف عملی تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب است.

IF OBJECT_ID(N'dbo.DemoClusteredIndexE10', N'U') IS NOT NULL
        DROP TABLE dbo.DemoClusteredIndexE10;
    
    CREATE TABLE dbo.DemoClusteredIndexE10
    (
        RowID       int IDENTITY(1,1) NOT NULL,
        CustomerID  int NOT NULL,
        ExternalCode varchar(30) NULL,
        OrderDate   date NOT NULL,
        Status      tinyint NULL,
        Amount      decimal(12,2) NOT NULL,
        Description nvarchar(200) NULL
    );
    
    INSERT INTO dbo.DemoClusteredIndexE10
        (CustomerID, ExternalCode, OrderDate, Status, Amount, Description)
    VALUES
        (101, 'A-1001', '2026-07-01', 1, 125000.00, N'سفارش فعال'),
        (102, 'A-1002', '2026-07-12', 2,  84000.00, N'سفارش بسته'),
        (101, 'A-1003', '2026-07-20', NULL, 99000.00, N'در انتظار بررسی');
    
    CREATE CLUSTERED INDEX IX_DemoClusteredIndex_E10
        ON dbo.DemoClusteredIndexE10(OrderDate DESC, RowID);
    
    SELECT name, type_desc, is_unique, has_filter
    FROM sys.indexes
    WHERE object_id = OBJECT_ID(N'dbo.DemoClusteredIndexE10')
      AND name = N'IX_DemoClusteredIndex_E10';
    
    SELECT CustomerID, OrderDate, Amount
    FROM dbo.DemoClusteredIndexE10
    WHERE CustomerID = 101
    ORDER BY OrderDate DESC;
    
نام یا شاخص کنترلنوع مورد انتظارنتیجه نمونه
IX_DemoClusteredIndex_E10CLUSTEREDتعریف در نمای سیستمی قابل مشاهده است و Query کنترل بدون خطای ساختاری اجرا می‌شود.

نکته کاربردی: نتیجه نهایی باید با Actual Execution Plan، STATISTICS IO و زمان اجرا در محیط آزمایشی مقایسه شود. برای ساخت ایندکس خوشه‌ای همچنین باید انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را در بازبینی نهایی ثبت کرد.

خطاهای رایج و روش عیب‌یابی

خطای Duplicate Name زمانی رخ می‌دهد که نام ایندکس روی همان جدول از قبل وجود داشته باشد. پیش از Deployment با sys.indexes وضعیت را بررسی کنید و تصمیم بگیرید عملیات باید Create، Rebuild یا جایگزینی با DROP_EXISTING باشد. حذف خودکار ایندکس بدون شناخت وابستگی‌ها خطرناک است.

خطاهای مربوط به ستون، نوع داده یا طول کلید معمولاً از تفاوت Schema محیط‌ها ناشی می‌شوند. اسکریپت باید در پایگاه مقصد و با نام Schema صریح اجرا شود. برای داده‌های XML، Spatial، Full-Text و Columnstore پیش‌نیازهای اختصاصی را جداگانه کنترل کنید.

اگر دستور موفق بود اما Query سریع نشد، مسئله الزاماً از Create نیست. تبدیل ضمنی، عبارت غیرSARGable، Statistics قدیمی، پارامتر نامناسب یا Key Lookup پرهزینه می‌تواند باعث کنار گذاشته‌شدن ایندکس شود. Actual Plan پاسخ دقیق‌تری از حدس ارائه می‌دهد.

در این موضوع، انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی مهم‌ترین کنترل اختصاصی است. خطای عملیاتی فقط پیام SQL Server نیست؛ رشد Log، Blocking طولانی یا افزایش هزینه DML نیز یک شکست استقرار محسوب می‌شود.

ملاحظات کارایی و پایش

قبل و بعد از تغییر، SET STATISTICS IO و SET STATISTICS TIME را برای Query ثابت اجرا کنید. Logical Reads معیار مناسبی برای کاهش کار موتور است، اما باید CPU، Elapsed Time، Memory Grant و Waitها نیز کنار آن دیده شوند. یک نتیجه سریع در Cache گرم ممکن است تصویر ناقصی بدهد.

نمای sys.dm_db_index_usage_stats تعداد Seek، Scan، Lookup و Update را نشان می‌دهد، ولی پس از Restart ریست می‌شود. داده پایش را دوره‌ای ذخیره کنید تا ایندکس کم‌مصرف با ایندکس تازه‌ساخته اشتباه نشود. Query Store نیز تغییر Plan و Regression را قابل پیگیری می‌کند.

هر ایندکس جدید هزینه نوشتن دارد. اگر جدول تراکنشی پرتغییر است، تعداد و عرض کلیدها را محدود کنید. برای گزارش‌های حجیم، ساختار Columnstore یا گزارش جداگانه ممکن است از چند ایندکس Rowstore عریض مناسب‌تر باشد.

Fragmentation تنها معیار نگهداری نیست. روی ساختارهای کوچک اثر آن ناچیز است و در Columnstore باید کیفیت Rowgroup و تعداد ردیف‌های Deleted نیز دیده شود. برنامه نگهداری باید با نوع ساخت ایندکس خوشه‌ای سازگار باشد.

بهترین روش‌ها

  1. نیاز را با Query واقعی و Plan معتبر اثبات کنید.
  2. تعریف‌های موجود را برای هم‌پوشانی و امکان ادغام بررسی کنید.
  3. کلید را تا حد ممکن باریک و هدفمند نگه دارید.
  4. گزینه‌های نسخه و Edition مقصد را پیش از استقرار کنترل کنید.
  5. ساخت را در محیط آزمایشی با حجم نزدیک به تولید زمان‌گیری کنید.
  6. اثر روی DML، Log، Backup و Replication را بسنجید.
  7. پس از استقرار Plan و شاخص‌های عملکرد را دوباره اندازه بگیرید.
  8. مالک، دلیل ایجاد و تاریخ بازبینی ایندکس را مستند کنید.
  9. برای ساخت ایندکس خوشه‌ای، انتخاب کلیدی باریک، پایدار، یکتا یا نزدیک به یکتا و ترجیحاً افزایشی را به چک‌لیست اضافه کنید.
  10. در صورت نبود منفعت پایدار، با برنامه کنترل‌شده تغییر را بازگردانید.

سؤالات متداول

سؤال 1: CREATE CLUSTERED INDEX دقیقاً چه کاری انجام می‌دهد؟

CREATE CLUSTERED INDEX ساختاری ایجاد می‌کند که برای تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب طراحی شده است. موتور SQL Server با توجه به Predicate، آمار و هزینه تخمینی تصمیم می‌گیرد از آن استفاده کند؛ بنابراین ایجاد ساختار به‌تنهایی تضمین‌کننده سریع‌ترشدن همه Queryها نیست.

سؤال 2: چه زمانی ساخت ایندکس خوشه‌ای انتخاب مناسبی است؟

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

سؤال 3: آیا افزودن این ایندکس هزینه پروژه را کاهش می‌دهد؟

اگر گلوگاه درست تشخیص داده شده باشد، کاهش زمان پاسخ، مصرف CPU و تعداد خواندن می‌تواند هزینه زیرساخت و پشتیبانی را کم کند. در پروژه حرفه‌ای باید هزینه ساخت، فضای دیسک، Log و نگهداری DML نیز در محاسبه بازگشت سرمایه وارد شود.

سؤال 4: برای سفارش طراحی ساخت ایندکس خوشه‌ای چه اطلاعاتی لازم است؟

طرح جدول، Queryهای واقعی، Actual Execution Plan، حجم و رشد داده، نسخه SQL Server، پنجره نگهداری و شاخص‌های SLA اطلاعات پایه هستند. بدون این داده‌ها پیشنهاد ایندکس بیشتر شبیه حدس است تا یک تصمیم مهندسی قابل اندازه‌گیری.

سؤال 5: تفاوت این روش با یک ایندکس عمومی چیست؟

تفاوت اصلی در هدف ذخیره‌سازی و مسیر دسترسی است. CREATE CLUSTERED INDEX بر تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب تمرکز دارد، در حالی که یک تعریف عمومی ممکن است فقط یک ستون را بدون توجه به پوشش Query، توزیع داده و هزینه تغییرات ایندکس کند.

سؤال 6: آیا می‌توان پیاده‌سازی را بدون توقف سرویس انجام داد؟

این موضوع به نوع ایندکس، نسخه و Edition، اندازه جدول، گزینه ONLINE و الگوی تراکنش بستگی دارد. حتی عملیات Online نیز می‌تواند قفل‌های کوتاه یا مصرف منابع قابل توجه داشته باشد؛ بنابراین زمان‌بندی، پایش و برنامه بازگشت ضروری است.

سؤال 7: رایج‌ترین خطا هنگام اجرای CREATE CLUSTERED INDEX چیست؟

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

سؤال 8: اثر ساخت ایندکس خوشه‌ای بر Performance چگونه سنجیده می‌شود؟

مقایسه باید با Query و پارامتر یکسان، Cache کنترل‌شده، Actual Execution Plan، SET STATISTICS IO و SET STATISTICS TIME انجام شود. فقط زمان یک اجرای منفرد معیار کافی نیست؛ خواندن منطقی، Memory Grant، Spill و اثر هم‌زمانی را هم ثبت کنید.

سؤال 9: بهترین روش نگهداری این ایندکس چیست؟

بر اساس نرخ تغییر، Fragmentation یا کیفیت Rowgroup، آمار مصرف و فضای ذخیره‌سازی برنامه نگهداری بسازید. بازسازی زمان‌بندی‌شده و کورکورانه مناسب نیست؛ تصمیم نگهداری باید مبتنی بر اندازه، Page Count، نوع ساختار و اثر واقعی بر Query باشد.

سؤال 10: این دستور با کدام نسخه‌های SQL Server سازگار است؟

هسته دستور در نسخه‌های پشتیبان آن قابل استفاده است، اما گزینه‌ها و قابلیت‌های تکمیلی میان نسخه‌ها، Editionها و سرویس‌های ابری تفاوت دارند. پیش از استفاده از ONLINE، فشرده‌سازی، Columnstore پیشرفته یا گزینه‌های خاص، مستندات همان نسخه سرور را کنترل کنید.

سؤالات مصاحبه تخصصی

پرسش مصاحبه 1: چگونه ثابت می‌کنید ساخت ایندکس خوشه‌ای لازم است؟

با استخراج Queryهای پرهزینه از Query Store یا مانیتورینگ، بررسی Plan، سنجش Selectivity و مقایسه IO قبل و بعد. پاسخ حرفه‌ای باید هزینه نوشتن و نگهداری را نیز کنار منفعت خواندن قرار دهد.

پرسش مصاحبه 2: ترتیب ستون‌ها را چگونه انتخاب می‌کنید؟

ستون‌های Equality، Range، Join و Sort را بر اساس الگوی Query و توزیع داده تحلیل می‌کنم. قانون ثابت جایگزین آزمایش نیست و کلید نهایی باید با چند Query مهم و پارامترهای واقعی اعتبارسنجی شود.

پرسش مصاحبه 3: اگر Optimizer از ایندکس استفاده نکرد چه می‌کنید؟

آمار، SARGability، تبدیل ضمنی، Parameter Sniffing، تخمین Cardinality و هزینه Lookup را بررسی می‌کنم. اجبار Hint آخرین انتخاب است، زیرا ممکن است با تغییر داده یا نسخه به تصمیم نامناسب تبدیل شود.

پرسش مصاحبه 4: چه شاخص‌هایی بعد از استقرار پایش می‌شوند؟

زمان پاسخ، Logical Read، CPU، تعداد Scan و Seek، نرخ Update، فضای ایندکس، انتظارهای قفل و تغییر Plan پایش می‌شوند. هدف اثبات پایداری منفعت در بار واقعی است.

پرسش مصاحبه 5: برنامه بازگشت برای این تغییر چیست؟

اسکریپت حذف یا بازگردانی تعریف قبلی، نسخه پشتیبان DDL، معیار توقف، زمان مجاز و مسئول تصمیم مشخص می‌شوند. برای جدول بزرگ، ظرفیت Log و فضای TempDB نیز قبل از عملیات برآورد می‌شود.

چک‌لیست نهایی

  • نام پایگاه، Schema، جدول و ستون‌ها تأیید شده‌اند.
  • نسخه پشتیبان تعریف قبلی و برنامه Rollback آماده است.
  • فضای Data File، Log و TempDB بررسی شده است.
  • Query و Plan مبنا پیش از تغییر ذخیره شده‌اند.
  • مثال استقرار در محیط آزمایشی بدون خطا اجرا شده است.
  • قفل، زمان اجرا و اثر روی کاربران پایش می‌شود.
  • آمار IO و زمان پس از ساخت دوباره ثبت می‌شوند.
  • مستندات و تاریخ بازبینی بعدی ثبت شده‌اند.

جمع‌بندی

CREATE CLUSTERED INDEX زمانی ارزشمند است که تعریف آن از نیاز واقعی استخراج و اثرش با اندازه‌گیری اثبات شود. این دستور برای تعیین ساختار فیزیکی ردیف‌های جدول بر پایه کلید خوشه‌ای و حذف هزینه جست‌وجوی اضافی در سناریوهای مناسب به کار می‌رود، اما هزینه نوشتن، فضا و نگهداری باید همراه با منفعت خواندن سنجیده شود.

ده مثال این مقاله الگوهای پایه تا کنترل عملیاتی را نشان دادند. برای محیط تولید، نام‌ها و ستون‌ها را با Schema خود تطبیق دهید، اسکریپت را در Staging اجرا کنید و پس از استقرار نیز Plan و شاخص‌های کارایی را پایش کنید.

برای مقایسه این روش با سایر ساختارها به مقاله مادر آموزش انواع دستور CREATE INDEX بازگردید.

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

حرف 500 حداکثر