ایندکس ستونی غیرخوشهای در SQL Server
ایندکس ستونی غیرخوشهای در SQL Server
ایندکس ستونی غیرخوشهای یا NCCI یک نسخه ستونی از ستونهای انتخابی را کنار ساختار Rowstore نگه میدارد. این گزینه برای تحلیل بلادرنگ روی سامانههای تراکنشی و افزودن مسیر تحلیلی بدون تبدیل کامل جدول مناسب است. در این راهنما موضوع از سطح مقدماتی تا طراحی عملی، خطاهای رایج، ملاحظات کارایی و سناریوهای نگهداری بررسی میشود.
مخاطب مقاله برنامهنویسان، مدیران پایگاه داده و تحلیلگرانی هستند که میخواهند Nonclustered Columnstore Index را بدون تصمیمهای حدسی در Microsoft SQL Server بهکار بگیرند. بازگشت به راهنمای جامع کارایی Columnstore در SQL Server
تعریف و جایگاه موضوع
ایندکس ستونی غیرخوشهای یا NCCI یک نسخه ستونی از ستونهای انتخابی را کنار ساختار Rowstore نگه میدارد. این گزینه برای تحلیل بلادرنگ روی سامانههای تراکنشی و افزودن مسیر تحلیلی بدون تبدیل کامل جدول مناسب است.
این قابلیت را باید در کنار مفاهیم Nonclustered Columnstore Index، Rowstore، Operational Analytics و Filtered Index تحلیل کرد. تصمیم درست تنها با مشاهده یک Query سریع حاصل نمیشود؛ بلکه نرخ رشد داده، الگوی DML، نحوه بارگذاری، محدودیت منابع و زمان نگهداری نیز باید وارد مدل تصمیم شوند.
نکته نسخه: پشتیبانی و محدودیتهای NCCI در نسخههای مختلف SQL Server تغییر کرده است؛ پیش از طراحی، ماتریس قابلیت نسخه مقصد بررسی شود.
چرا این موضوع مهم است؟
در جداول تحلیلی بزرگ، تفاوت میان طراحی درست و اجرای صرف یک دستور میتواند به اختلاف قابلتوجه در IO، CPU و زمان پاسخ منجر شود. ایندکس ستونی غیرخوشهای وقتی ارزش واقعی ایجاد میکند که با هدف کسبوکار، الگوی Query و ظرفیت زیرساخت هماهنگ باشد.
- تحلیل بلادرنگ OLTP
- داشبورد مدیریتی
- گزارش روی جدول تراکنش
- فیلتر دادههای گرم
- همزیستی با B-tree
به همین دلیل لازم است معیار موفقیت پیش از پیادهسازی تعریف شود. برای نمونه میتوان زمان گزارش ماهانه، تعداد Rowgroupهای کمحجم، درصد ردیفهای حذفشده، حجم Log یا تعداد Segmentهای خواندهشده را بهعنوان شاخص پایه ثبت کرد.
این نمودار اجزای کلیدی «ایندکس ستونی غیرخوشهای» و ارتباط میان Nonclustered Columnstore Index، Rowstore و Operational Analytics را نشان میدهد.
نحو، اجزا و پارامترهای اصلی
نحو پایه زیر نقطه شروع است. نام شیء، Schema، پارتیشن و گزینهها باید با محیط واقعی جایگزین شوند. در رشتههای فارسی SQL از پیشوند N استفاده شده تا داده یونیکد درست ذخیره شود.
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_SalesAnalytics ON dbo.Sales(OrderDate, CustomerID, Amount);
اجزای کلیدی
| مفهوم | نقش در موضوع | نکته عملی |
|---|
| Nonclustered Columnstore Index | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | تنها ستونهای تحلیلی را اضافه کنید |
| Rowstore | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | فیلتر داده سرد/گرم |
| Operational Analytics | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | پایش تأثیر بر INSERT و UPDATE |
| Filtered Index | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | مقایسه Plan قبل و بعد |
| Batch Mode | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | بازبینی دورهای استفاده |
| Included Columns | بخشی از معماری یا رفتار ایندکس ستونی غیرخوشهای | تنها ستونهای تحلیلی را اضافه کنید |
نوع خروجی بسته به موضوع ممکن است یک ساختار ایندکس، Plan اجرایی، مجموعه Rowgroup، شمارنده DMV یا مقدار عددی باشد. همیشه خروجی را با Metadata و Plan واقعی تأیید کنید؛ پیام موفقیت دستور بهتنهایی نشاندهنده بهبود نیست.
فرایند تصمیمگیری و پیادهسازی
- Workload اصلی را مشخص کنید و Queryهای پرتکرار مرتبط با ایندکس ستونی غیرخوشهای را از Query Store یا مانیتورینگ استخراج کنید.
- وضعیت فعلی Rowstore و Operational Analytics را ثبت کنید تا خط پایه قابل مقایسه باشد.
- Syntax را در محیط آزمایشی اجرا کنید و اثر آن را روی هزینه نگهداری DML و انتخاب ستون بسنجید.
- سناریوهای بارگذاری، حذف، بهروزرسانی، گزارشگیری و بازیابی خطا را جداگانه آزمایش کنید.
- پس از تأیید، اجرای Production را با پنجره تغییر، Rollback Plan و گزارش کنترلی انجام دهید.
این روش مرحلهای مانع آن میشود که یک بهبود محلی، هزینه پنهان در ETL یا عملیات تراکنشی ایجاد کند. همچنین مستندسازی خروجیهای قبل و بعد، تصمیمهای نگهداری آینده را قابل دفاع میسازد.
در این جریان، داده از مرحله ورودی عبور میکند، در نقطههای کنترلی مرتبط با Rowstore و Filtered Index ارزیابی میشود و سپس نتیجه قابل پایش تولید میگردد.
۱۰ مثال عملی از ساده تا حرفهای
مثال 1: مثال پایه و اجرای نخست
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی مثال پایه و اجرای نخست بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT SUM(Amount) AS total_amount FROM dbo.FactSalesDemo;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,137 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 40 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ هزینه نگهداری DML را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 2: کار روی داده نمونه واقعی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی کار روی داده نمونه واقعی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT CustomerID,SUM(Amount) FROM dbo.FactSalesDemo GROUP BY CustomerID;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,274 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 38 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ انتخاب ستون را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 3: استفاده در SELECT تحلیلی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی استفاده در SELECT تحلیلی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT TOP(100) * FROM dbo.FactSalesDemo WHERE SaleID BETWEEN 1 AND 100 ORDER BY SaleID;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,411 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 36 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ Filtered NCCI را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 4: فیلتر و شرط کاربردی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی فیلتر و شرط کاربردی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT ProductID,AVG(Amount) FROM dbo.FactSalesDemo WHERE OrderDate>='2026-01-01' GROUP BY ProductID;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,548 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 34 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ Batch Mode را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 5: ترکیب با قابلیت دیگر
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی ترکیب با قابلیت دیگر بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
INSERT INTO dbo.FactSalesDemo VALUES (30001,'2026-07-27',77,8,2,55.00);
SELECT * FROM dbo.FactSalesDemo WHERE SaleID=30001;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,685 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 32 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ اندازه حافظه را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 6: رفتار با NULL یا تغییر داده
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی رفتار با NULL یا تغییر داده بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
UPDATE dbo.FactSalesDemo SET Amount=Amount*1.05 WHERE SaleID<=10;
SELECT SUM(Amount) FROM dbo.FactSalesDemo;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,822 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 30 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ هزینه نگهداری DML را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 7: حالت مرزی و کنترل Metadata
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی حالت مرزی و کنترل Metadata بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT i.name,i.type_desc,i.has_filter FROM sys.indexes i WHERE i.object_id=OBJECT_ID(N'dbo.FactSalesDemo');
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 25,959 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 28 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ انتخاب ستون را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 8: سناریوی گزارشگیری سازمانی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی سناریوی گزارشگیری سازمانی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SET STATISTICS IO ON;
SELECT YEAR(OrderDate),SUM(Amount) FROM dbo.FactSalesDemo GROUP BY YEAR(OrderDate);
SET STATISTICS IO OFF;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 26,096 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 26 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ Filtered NCCI را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 9: روش اشتباه و نسخه اصلاحی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی روش اشتباه و نسخه اصلاحی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
DROP INDEX NCCI_FactSalesDemo ON dbo.FactSalesDemo;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo ON dbo.FactSalesDemo(OrderDate,CustomerID,Amount);
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 26,233 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 24 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ Batch Mode را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
مثال 10: آزمون کارایی و بهینهسازی
در این مثال، «ایندکس ستونی غیرخوشهای» در سناریوی آزمون کارایی و بهینهسازی بررسی میشود. Query بهگونهای نوشته شده که در یک محیط آزمایشی SQL Server قابل اجرا باشد و نتیجه آن با DMV، خروجی تجمیعی یا Metadata کنترل شود.
USE tempdb;
DROP TABLE IF EXISTS dbo.FactSalesDemo;
CREATE TABLE dbo.FactSalesDemo
(
SaleID bigint NOT NULL,
OrderDate date NOT NULL,
CustomerID int NOT NULL,
ProductID int NOT NULL,
Quantity smallint NULL,
Amount decimal(18,2) NULL
);
INSERT INTO dbo.FactSalesDemo
(
SaleID, OrderDate, CustomerID, ProductID, Quantity, Amount
)
SELECT TOP (25000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
DATEADD(day, -ABS(CHECKSUM(NEWID())) % 730, CONVERT(date, '20260727')),
1 + ABS(CHECKSUM(NEWID())) % 5000,
1 + ABS(CHECKSUM(NEWID())) % 800,
1 + ABS(CHECKSUM(NEWID())) % 12,
CONVERT(decimal(18,2), 10 + ABS(CHECKSUM(NEWID())) % 50000 / 10.0)
FROM sys.all_objects AS a
CROSS JOIN sys.all_objects AS b;
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_FactSalesDemo
ON dbo.FactSalesDemo(OrderDate, CustomerID, ProductID, Quantity, Amount);
SELECT CustomerID,COUNT(*) AS orders,SUM(Amount) AS revenue FROM dbo.FactSalesDemo GROUP BY CustomerID HAVING COUNT(*)>3;
| شاخص | خروجی نمونه | تفسیر |
|---|
| وضعیت | COMPRESSED | ساختار برای اسکن تحلیلی آماده است |
| تعداد ردیف | 26,370 | مقدار نمونه برای مقایسه قبل و بعد |
| هزینه منطقی | 22 صفحه | خروجی نمونه و وابسته به محیط واقعی |
نکته فنی: هنگام استفاده از Nonclustered Columnstore Index فقط به موفقبودن دستور اکتفا نکنید؛ اندازه حافظه را قبل و بعد اندازه بگیرید و اثر آن را روی Workload واقعی ثبت کنید.
خطاهای رایج
خطاهای زیر در پروژههای واقعی مرتبط با Nonclustered Columnstore Index دیده میشوند. شدت هر خطا به حجم داده و نسخه SQL Server وابسته است، اما اصل کنترل برای همه محیطها یکسان است.
- پوشش بیش از حد ستونها
- افزایش هزینه DML
- انتخاب ستونهای کمارزش
- بیتوجهی به فیلتر
- تداخل با الگوی قفلگذاری
مهمترین هشدار: پوشش بیش از حد ستونها. پیش از هر تغییر گسترده، Backup/Restore آزمایشی، ظرفیت Log و امکان بازگشت را بررسی کنید.
ملاحظات کارایی و پایش
برای ارزیابی ایندکس ستونی غیرخوشهای حداقل پنج محور باید همزمان دیده شود: هزینه نگهداری DML, انتخاب ستون, Filtered NCCI, Batch Mode, اندازه حافظه. اندازهگیری تنها زمان اجرا ممکن است نتیجه گمراهکننده بدهد، زیرا Cache گرم، Parallelism، Memory Grant و بار همزمان روی نتیجه اثر دارند.
| معیار | چرا مهم است؟ | روش پیشنهادی |
|---|
| هزینه نگهداری DML | اثر مستقیم بر کیفیت یا هزینه ایندکس ستونی غیرخوشهای دارد | تنها ستونهای تحلیلی را اضافه کنید |
| انتخاب ستون | اثر مستقیم بر کیفیت یا هزینه ایندکس ستونی غیرخوشهای دارد | فیلتر داده سرد/گرم |
| Filtered NCCI | اثر مستقیم بر کیفیت یا هزینه ایندکس ستونی غیرخوشهای دارد | پایش تأثیر بر INSERT و UPDATE |
| Batch Mode | اثر مستقیم بر کیفیت یا هزینه ایندکس ستونی غیرخوشهای دارد | مقایسه Plan قبل و بعد |
| اندازه حافظه | اثر مستقیم بر کیفیت یا هزینه ایندکس ستونی غیرخوشهای دارد | بازبینی دورهای استفاده |
یک Snapshot منفرد برای تصمیم بلندمدت کافی نیست. داده پایش را در چند بازه کاری، پس از ETL و در ساعات اوج جمعآوری کنید تا روند واقعی مشخص شود.
این سناریو تفاوت میان اجرای بدون پایش و اجرای مبتنی بر Best Practice را برای ایندکس ستونی غیرخوشهای مقایسه میکند؛ معیارهای اصلی شامل هزینه نگهداری DML و انتخاب ستون هستند.
بهترین روشها
- تنها ستونهای تحلیلی را اضافه کنید
- فیلتر داده سرد/گرم
- پایش تأثیر بر INSERT و UPDATE
- مقایسه Plan قبل و بعد
- بازبینی دورهای استفاده
Best Practice بهمعنای اجرای یک نسخه ثابت برای همه سرورها نیست. باید توصیهها را با اندازه داده، Edition، Compatibility Level، معماری HA/DR و محدودیت پنجره نگهداری تطبیق داد.
پرسشهای متداول
ایندکس ستونی غیرخوشهای دقیقاً چه مشکلی را حل میکند؟
ایندکس ستونی غیرخوشهای یا NCCI یک نسخه ستونی از ستونهای انتخابی را کنار ساختار Rowstore نگه میدارد. این گزینه برای تحلیل بلادرنگ روی سامانههای تراکنشی و افزودن مسیر تحلیلی بدون تبدیل کامل جدول مناسب است. انتخاب آن باید براساس نوع بارکاری و معیارهای قابل اندازهگیری انجام شود.
برای شروع یادگیری Nonclustered Columnstore Index چه پیشنیازی لازم است؟
آشنایی با Execution Plan، ایندکسها و دستورات پایه T-SQL کافی است. سپس باید مفاهیم Rowstore و Operational Analytics را روی یک پایگاه داده آزمایشی مشاهده کنید.
آیا ایندکس ستونی غیرخوشهای برای همه پروژههای تجاری مناسب است؟
خیر. سودمندی آن به حجم داده، نسبت خواندن به نوشتن، SLA گزارشها و هزینه نگهداری وابسته است. ارزیابی فنی یا مشاوره SQL Server پیش از استقرار میتواند از هزینههای بازطراحی جلوگیری کند.
هزینه پیادهسازی ایندکس ستونی غیرخوشهای چگونه برآورد میشود؟
برآورد باید شامل تحلیل Workload، طراحی آزمایش، زمان مهاجرت، پایش پس از اجرا و آموزش تیم باشد. اندازه جدول و حساسیت توقف سرویس نیز روی زمان انجام پروژه اثر مستقیم دارد.
تفاوت ایندکس ستونی غیرخوشهای با یک ایندکس یا روش عمومی چیست؟
روش عمومی معمولاً فقط ساختار یا دستور را میبیند، اما این موضوع روی Nonclustered Columnstore Index، Filtered Index و رفتار واقعی موتور تمرکز دارد. مقایسه باید با Plan، IO، CPU و مدت اجرا انجام شود.
چه زمانی برای اجرای پروژه یا دریافت خدمات مرتبط با Nonclustered Columnstore Index مناسب است؟
هنگامی که گزارشها کند شدهاند، رشد داده سریع است یا نگهداری فعلی نتیجه قابل پیشبینی ندارد، بررسی تخصصی ارزشمند است. بهتر است ابتدا Snapshot فنی و معیار موفقیت تعیین شود.
رایجترین خطا در استفاده از ایندکس ستونی غیرخوشهای چیست؟
یکی از خطاهای پرتکرار «پوشش بیش از حد ستونها» است. خطای دیگر تصمیمگیری بدون مقایسه قبل و بعد و بدون توجه به نسخه SQL Server است.
ایندکس ستونی غیرخوشهای چه اثری بر Performance دارد؟
اثر اصلی از مسیر هزینه نگهداری DML، انتخاب ستون و Filtered NCCI دیده میشود. نتیجه میتواند بسیار مثبت یا در Workload نامناسب منفی باشد، بنابراین تست کنترلشده ضروری است.
بهترین روش عملی برای ایندکس ستونی غیرخوشهای چیست؟
از یک محیط آزمایشی مشابه Production شروع کنید، تنها ستونهای تحلیلی را اضافه کنید و فیلتر داده سرد/گرم را اجرا کنید و معیارها را در Query Store یا سامانه پایش ثبت نمایید.
سازگاری Nonclustered Columnstore Index با نسخههای SQL Server چگونه است؟
پشتیبانی و محدودیتهای NCCI در نسخههای مختلف SQL Server تغییر کرده است؛ پیش از طراحی، ماتریس قابلیت نسخه مقصد بررسی شود. پیش از انتشار در Production، Syntax و گزینههای قابل پشتیبانی را روی همان Edition، Version و Compatibility Level بررسی کنید.
سؤالات مصاحبه
پاسخ مناسب به پرسشهای زیر باید علاوه بر تعریف، شامل سناریو، Trade-off، معیار اندازهگیری و نمونه T-SQL باشد.
- تفاوت Nonclustered Columnstore Index و Rowstore را با یک سناریوی واقعی توضیح دهید.
- برای سنجش اثر Nonclustered Columnstore Index چه شاخصهایی را قبل و بعد ثبت میکنید؟
- در چه شرایطی «پوشش بیش از حد ستونها» باعث افت کارایی میشود؟
- چگونه با استفاده از Operational Analytics و Filtered Index مشکل را عیبیابی میکنید؟
- در طراحی یک Job سازمانی برای ایندکس ستونی غیرخوشهای چه کنترل خطا و Rollback در نظر میگیرید؟
- چرا توصیه «تنها ستونهای تحلیلی را اضافه کنید» برای محیط Production مهم است؟
چکلیست نهایی
- نسخه و Compatibility Level برای Nonclustered Columnstore Index کنترل شد.
- خط پایه IO، CPU، Duration و فضای مصرفی ثبت شد.
- Query و Syntax در محیط آزمایشی اجرا شد.
- اثرات DML و ETL جداگانه سنجیده شد.
- خروجی DMV یا Metadata پس از اجرا بررسی شد.
- Rollback Plan و ظرفیت Log مشخص شد.
- گزارش مقایسه قبل و بعد ذخیره شد.
- Job یا رویه نگهداری دارای شرط و کنترل خطا است.
جمعبندی
ایندکس ستونی غیرخوشهای زمانی مفید است که از حالت یک دستور منفرد خارج و به یک فرایند اندازهگیریشده تبدیل شود. ایندکس ستونی غیرخوشهای یا NCCI یک نسخه ستونی از ستونهای انتخابی را کنار ساختار Rowstore نگه میدارد. این گزینه برای تحلیل بلادرنگ روی سامانههای تراکنشی و افزودن مسیر تحلیلی بدون تبدیل کامل جدول مناسب است. در عمل باید با نسخه SQL Server، شکل داده و هدف گزارشگیری سازگار شود.
برای مطالعه ارتباط این موضوع با سایر اجزای Columnstore، راهنمای جامع کارایی Columnstore در SQL Server را ببینید.
خدمات برنامهنویسی و پایگاه داده
برنامهنویسی در اصفهان
قبول سفارشهای برنامهنویسی و پایگاه داده: 09131253620
انجام پروژههای برنامهنویسی، آموزش برنامهنویسی و آموزش پایگاه داده SQL Server با رویکرد حرفهای، مستندسازی مناسب و قابلیت توسعه انجام میشود.
مجموعهای معتبر با سابقه فعالیت حرفهای از سال ۱۳۷۵ شمسی
از سال ۱۳۷۵ شمسی تاکنون در زمینه طراحی و اجرای پروژههای برنامهنویسی، پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری فعالیت میکنیم.
برای سفارش پروژههای برنامهنویسی و پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری جدید، با شماره تلفن همراه 09131253620 تماس حاصل فرمایید.
ایتا، واتساپ و تماس مستقیم: +989131253620
تماس با ما