Đây là một vấn đề khó giải quyết nói chung, nhưng có một vài điều chúng ta có thể làm để giúp trình tối ưu hóa chọn một kế hoạch. Kịch bản lệnh này tạo một bảng có 10.000 hàng với phân phối các hàng giả ngẫu nhiên đã biết để minh họa:
CREATE TABLE dbo.SomeDateTable
(
Id INTEGER IDENTITY(1, 1) PRIMARY KEY NOT NULL,
StartDate DATETIME NOT NULL,
EndDate DATETIME NOT NULL
);
GO
SET STATISTICS XML OFF
SET NOCOUNT ON;
DECLARE
@i INTEGER = 1,
@s FLOAT = RAND(20120104),
@e FLOAT = RAND();
WHILE @i <= 10000
BEGIN
INSERT dbo.SomeDateTable
(
StartDate,
EndDate
)
VALUES
(
DATEADD(DAY, @s * 365, {d '2009-01-01'}),
DATEADD(DAY, @s * 365 + @e * 14, {d '2009-01-01'})
)
SELECT
@s = RAND(),
@e = RAND(),
@i += 1
END
Câu hỏi đầu tiên là làm thế nào để lập chỉ mục bảng này. Một tùy chọn là cung cấp hai chỉ mục trên các DATETIME
cột, vì vậy trình tối ưu hóa ít nhất có thể chọn tìm kiếm trên StartDate
hoặc EndDate
.
CREATE INDEX nc1 ON dbo.SomeDateTable (StartDate, EndDate)
CREATE INDEX nc2 ON dbo.SomeDateTable (EndDate, StartDate)
Đương nhiên, sự bất bình đẳng trên cả hai StartDate
và EndDate
có nghĩa là chỉ một cột trong mỗi chỉ mục có thể hỗ trợ tìm kiếm trong truy vấn mẫu, nhưng đây là cách tốt nhất chúng ta có thể làm. Chúng tôi có thể xem xét làm cho cột thứ hai trong mỗi chỉ mục INCLUDE
thay vì một khóa, nhưng chúng tôi có thể có các truy vấn khác có thể thực hiện tìm kiếm bằng nhau trên cột hàng đầu và tìm kiếm bất bình đẳng trên cột thứ hai. Ngoài ra, chúng tôi có thể nhận được số liệu thống kê tốt hơn theo cách này. Dù sao...
DECLARE
@StartDateBegin DATETIME = {d '2009-08-01'},
@StartDateEnd DATETIME = {d '2009-10-15'},
@EndDateBegin DATETIME = {d '2009-08-05'},
@EndDateEnd DATETIME = {d '2009-10-22'}
SELECT
COUNT_BIG(*)
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
AND sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
Truy vấn này sử dụng các biến, vì vậy, nói chung, trình tối ưu hóa sẽ đoán tính chọn lọc và phân phối, dẫn đến ước tính số lượng thẻ được đoán là 81 hàng . Trong thực tế, truy vấn tạo ra 2076 hàng, sự khác biệt có thể quan trọng trong một ví dụ phức tạp hơn.
Trên SQL Server 2008 SP1 CU5 trở lên (hoặc R2 RTM CU1), chúng tôi có thể tận dụng Tối ưu hóa nhúng tham số để có được ước tính tốt hơn, chỉ bằng cách thêm OPTION (RECOMPILE)
vào SELECT
truy vấn ở trên. Điều này gây ra một quá trình biên dịch ngay trước khi lô thực thi, cho phép SQL Server 'nhìn thấy' các giá trị tham số thực và tối ưu hóa cho các giá trị đó. Với thay đổi này, ước tính cải thiện thành 468 hàng (mặc dù bạn cần kiểm tra kế hoạch thời gian chạy để thấy điều này). Ước tính này tốt hơn 81 hàng, nhưng vẫn chưa hoàn thành. Các tiện ích mở rộng mô hình được bật bởi cờ theo dõi 2301 có thể giúp ích trong một số trường hợp, nhưng không phải với truy vấn này.
Vấn đề là nơi các hàng đủ điều kiện của hai phạm vi tìm kiếm trùng nhau. Một trong những giả định đơn giản hóa được thực hiện trong thành phần ước tính chi phí và giá trị của trình tối ưu hóa là các biến vị ngữ là độc lập (vì vậy nếu cả hai đều có độ chọn lọc là 50%, kết quả của việc áp dụng cả hai được coi là đủ điều kiện 50% 50% = 25% số hàng ). Trong trường hợp loại tương quan này là một vấn đề, chúng ta thường có thể làm việc xung quanh nó với các số liệu thống kê nhiều cột và / hoặc được lọc. Với hai phạm vi với điểm bắt đầu và điểm kết thúc chưa biết, điều này trở nên không thực tế. Đây là nơi đôi khi chúng ta phải dùng đến cách viết lại truy vấn thành một biểu mẫu xảy ra để đưa ra ước tính tốt hơn:
SELECT COUNT(*) FROM
(
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.StartDate BETWEEN @StartDateBegin AND @StartDateEnd
INTERSECT
SELECT
sdt.Id
FROM dbo.SomeDateTable AS sdt
WHERE
sdt.EndDate BETWEEN @EndDateBegin AND @EndDateEnd
) AS intersected (id)
OPTION (RECOMPILE)
Hình thức này xảy ra để tạo ra ước tính thời gian chạy là 2110 hàng (so với năm 2076 thực tế). Trừ khi bạn có TF 2301, trong trường hợp đó, các kỹ thuật mô hình nâng cao hơn sẽ nhìn xuyên qua thủ thuật và đưa ra ước tính chính xác như trước: 468 hàng.
Một ngày SQL Server có thể nhận được hỗ trợ riêng cho các khoảng thời gian. Nếu điều đó đi kèm với sự hỗ trợ thống kê tốt, các nhà phát triển có thể sợ các kế hoạch truy vấn điều chỉnh như thế này ít hơn một chút.