Tôi có một cột được tính toán bền vững trên một bảng được tạo thành các cột được nối đơn giản, ví dụ:
CREATE TABLE dbo.T
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY,
A VARCHAR(20) NOT NULL,
B VARCHAR(20) NOT NULL,
C VARCHAR(20) NOT NULL,
D DATE NULL,
E VARCHAR(20) NULL,
Comp AS A + '-' + B + '-' + C PERSISTED NOT NULL
);
Trong trường hợp này Comp
không phải là duy nhất và D là hợp lệ kể từ ngày của mỗi kết hợp A, B, C
, do đó tôi sử dụng truy vấn sau để lấy ngày kết thúc cho mỗi kết quả A, B, C
(về cơ bản là ngày bắt đầu tiếp theo cho cùng một giá trị Comp):
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1
WHERE t1.D IS NOT NULL -- DON'T CARE ABOUT INACTIVE RECORDS
ORDER BY t1.Comp;
Sau đó tôi đã thêm một chỉ mục vào cột được tính toán để hỗ trợ truy vấn này (và cả các mục khác):
CREATE NONCLUSTERED INDEX IX_T_Comp_D ON dbo.T (Comp, D) WHERE D IS NOT NULL;
Kế hoạch truy vấn tuy nhiên làm tôi ngạc nhiên. Tôi đã nghĩ rằng vì tôi có một mệnh đề where nêu rõ điều đó D IS NOT NULL
và tôi đang sắp xếp theo Comp
, và không tham chiếu bất kỳ cột nào ngoài chỉ mục mà chỉ mục trên cột được tính toán có thể được sử dụng để quét t1 và t2, nhưng tôi thấy một chỉ mục được nhóm quét.
Vì vậy, tôi buộc phải sử dụng chỉ số này để xem liệu nó có mang lại một kế hoạch tốt hơn không:
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1 WITH (INDEX (IX_T_Comp_D))
WHERE t1.D IS NOT NULL
ORDER BY t1.Comp;
Mà đã cho kế hoạch này
Điều này cho thấy một tra cứu khóa đang được sử dụng, các chi tiết đó là:
Bây giờ, theo tài liệu SQL-Server:
Bạn có thể tạo một chỉ mục trên một cột được tính toán được xác định bằng biểu thức xác định, nhưng không chính xác, nếu cột được đánh dấu PERSISTED trong câu lệnh CREATE TABLE hoặc ALTER TABLE. Điều này có nghĩa là Công cụ cơ sở dữ liệu lưu trữ các giá trị được tính toán trong bảng và cập nhật chúng khi bất kỳ cột nào khác mà cột được tính phụ thuộc được cập nhật. Công cụ cơ sở dữ liệu sử dụng các giá trị bền vững này khi nó tạo một chỉ mục trên cột và khi chỉ mục được tham chiếu trong một truy vấn. Tùy chọn này cho phép bạn tạo một chỉ mục trên một cột được tính toán khi Cơ sở dữ liệu không thể chứng minh chính xác liệu một hàm trả về các biểu thức cột được tính toán, đặc biệt là hàm CLR được tạo trong .NET Framework, có tính xác định và chính xác.
Vì vậy, nếu, như các tài liệu nói "Công cụ cơ sở dữ liệu lưu trữ các giá trị được tính toán trong bảng" và giá trị cũng đang được lưu trữ trong chỉ mục của tôi, tại sao cần phải có Tra cứu khóa để lấy A, B và C khi chúng không được tham chiếu trong truy vấn nào cả? Tôi giả sử chúng đang được sử dụng để tính toán Comp, nhưng tại sao? Ngoài ra, tại sao truy vấn có thể sử dụng chỉ mục trên t2
, nhưng không bật t1
?
Truy vấn và DDL trên SQL Fiddle
NB Tôi đã gắn thẻ SQL Server 2008 vì đây là phiên bản mà sự cố chính của tôi gặp phải, nhưng tôi cũng có hành vi tương tự vào năm 2012.