Tỷ lệ phần trăm giữa các kế hoạch truy vấn là vô nghĩa để so sánh hoàn toàn. Bạn phải điểm chuẩn các truy vấn để có một so sánh hợp lệ. Ngoài ra, số lượng hàng nhỏ có xu hướng che giấu sự khác biệt về hiệu suất giữa các chiến lược lập chỉ mục. Bằng cách tăng số lượng hàng lên 10 triệu, bạn có thể có được một bức tranh rõ ràng hơn về sự khác biệt hiệu suất.
Có một tập lệnh mẫu tạo 3 bảng, hai bảng của bạn ở trên và một bảng thứ ba có cả chỉ mục được phân cụm và không phân cụm.
USE [tempdb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[t1](
[id] [int] IDENTITY(1,1) NOT NULL,
[c1] [varchar](200) NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t2](
[id] [int] IDENTITY(1,1) NOT NULL,
[c1] [varchar](200) NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[t3](
[id] [int] IDENTITY(1,1) NOT NULL,
[c1] [varchar](200) NULL
) ON [PRIMARY]
GO
CREATE CLUSTERED INDEX CIX_t1 ON t1(id)
CREATE NONCLUSTERED INDEX IX_t2 ON t2(id)
CREATE CLUSTERED INDEX CIX_t3 ON t3(id)
CREATE NONCLUSTERED INDEX IX_t3 ON t3(id)
Điền vào các bảng với 10 triệu hàng
DECLARE @i INT
DECLARE @j int
DECLARE @t DATETIME
SET NOCOUNT ON
SET @t = CURRENT_TIMESTAMP
SET @i = 0
WHILE @i < 10000000
BEGIN
--populate with strings with a length between 100 and 200
INSERT INTO t1 (c1) VALUES (REPLICATE('x', 101+ CAST(RAND(@i) * 100 AS INT)))
SET @i = @i + 1
END
PRINT 'Time to populate t1: '+ CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR(10)) + ' ms'
SET @t = CURRENT_TIMESTAMP
SET @i = 0
WHILE @i < 10000000
BEGIN
--populate with strings with a length between 100 and 200
INSERT INTO t2 (c1) VALUES (REPLICATE('x', 101+ CAST(RAND(@i) * 100 AS INT)))
SET @i = @i + 1
END
PRINT 'Time to populate t3: '+ CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR(10)) + ' ms'
SET @t = CURRENT_TIMESTAMP
SET @i = 0
WHILE @i < 10000000
BEGIN
--populate with strings with a length between 100 and 200
INSERT INTO t3 (c1) VALUES (REPLICATE('x', 101+ CAST(RAND(@i) * 100 AS INT)))
SET @i = @i + 1
END
PRINT 'Time to populate t3: '+ CAST(DATEDIFF(ms, @t, CURRENT_TIMESTAMP) AS VARCHAR(10)) + ' ms'
Chúng ta có thể sử dụng sys.dm_db_index_physical_stats để xem kích thước trên đĩa của các chỉ mục.
SELECT OBJECT_NAME(OBJECT_ID) table_name, index_id, index_type_desc,
record_count, page_count, page_count / 128.0 size_in_mb, avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('t1'), NULL, NULL, 'detailed')
WHERE index_level = 0
UNION ALL
SELECT OBJECT_NAME(OBJECT_ID) table_name, index_id, index_type_desc,
record_count, page_count, page_count / 128.0 size_in_mb, avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('t2'), NULL, NULL, 'detailed')
WHERE index_level = 0
UNION ALL
SELECT OBJECT_NAME(OBJECT_ID) table_name, index_id, index_type_desc,
record_count, page_count, page_count / 128.0 size_in_mb, avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID('t3'), NULL, NULL, 'detailed')
WHERE index_level = 0
Và kết quả:
table_name index_id page_count size_in_mb avg_record_size_in_bytes index_type_desc
t1 1 211698 1653.890625 167.543 CLUSTERED INDEX
t2 0 209163 1634.085937 165.543 HEAP
t2 2 22272 174.000000 16 NONCLUSTERED INDEX
t3 1 211698 1653.890625 167.543 CLUSTERED INDEX
t3 2 12361 96.570312 8 NONCLUSTERED INDEX
Chỉ số cụm của T1 có kích thước khoảng 1,6 GB. Chỉ số không phân cụm của T2 là 170 MB (tiết kiệm 90% trong IO). Chỉ số không phân cụm của T3 là 97 MB, hoặc ít hơn khoảng 95% IO so với T1.
Vì vậy, dựa trên yêu cầu IO, kế hoạch truy vấn ban đầu nên có nhiều hơn 10% / 90%, chứ không phải 38% / 62%. Ngoài ra, do chỉ mục không được phân cụm có khả năng phù hợp hoàn toàn trong bộ nhớ, sự khác biệt có thể vẫn lớn hơn, vì IO đĩa rất đắt.