Nó phụ thuộc vào dữ liệu trong bảng, chỉ mục của bạn, .... Khó có thể nói mà không thể so sánh các kế hoạch thực hiện / thống kê thời gian io +.
Sự khác biệt tôi mong đợi là việc lọc thêm xảy ra trước THAM GIA giữa hai bảng. Trong ví dụ của tôi, tôi đã thay đổi các bản cập nhật thành các lựa chọn để sử dụng lại các bảng của mình.
Kế hoạch thực hiện với "tối ưu hóa"
Kế hoạch thực hiện
Bạn thấy rõ một hoạt động của bộ lọc xảy ra, trong dữ liệu thử nghiệm của tôi không có bản ghi nào được lọc ra và kết quả là không có cải tiến nào được thực hiện.
Kế hoạch thực hiện, không có "tối ưu hóa"
Kế hoạch thực hiện
Bộ lọc không còn nữa, điều đó có nghĩa là chúng ta sẽ phải dựa vào phép nối để lọc ra các bản ghi không cần thiết.
(Các)
lý do khác Một lý do / hậu quả khác của việc thay đổi truy vấn có thể là, một kế hoạch thực hiện mới đã được tạo khi thay đổi truy vấn, diễn ra nhanh hơn. Một ví dụ về điều này là công cụ chọn một toán tử Tham gia khác, nhưng đó chỉ là phỏng đoán tại thời điểm này.
BIÊN TẬP:
Làm rõ sau khi nhận được hai kế hoạch truy vấn:
Truy vấn đang đọc 550M Hàng từ bảng lớn và lọc chúng ra.
Có nghĩa là vị ngữ là phần tử thực hiện hầu hết các bộ lọc, không phải là vị từ tìm kiếm. Kết quả là dữ liệu được đọc, nhưng cách ít được trả lại.
Làm cho máy chủ sql sử dụng một chỉ mục khác (kế hoạch truy vấn) / thêm một chỉ mục có thể giải quyết điều này.
Vậy tại sao truy vấn tối ưu hóa không có vấn đề tương tự?
Bởi vì một kế hoạch truy vấn khác nhau được sử dụng, với một lần quét thay vì tìm kiếm.
Không thực hiện bất kỳ tìm kiếm nào, mà chỉ trả về 4M hàng để làm việc.
Sự khác biệt tiếp theo
Bỏ qua sự khác biệt cập nhật (không có gì được cập nhật trên truy vấn được tối ưu hóa), một kết quả băm được sử dụng trên truy vấn được tối ưu hóa:
Thay vì một vòng lặp lồng nhau tham gia vào không được tối ưu hóa:
Một vòng lặp lồng nhau là tốt nhất khi một bảng nhỏ và một bảng khác lớn. Vì cả hai đều có cùng kích thước, tôi cho rằng khớp băm là lựa chọn tốt hơn trong trường hợp này.
Tổng quat
Truy vấn tối ưu hóa
Kế hoạch của truy vấn được tối ưu hóa có tính tương đồng, sử dụng phép nối khớp băm và cần thực hiện lọc IO ít hơn. Nó cũng sử dụng một bitmap để loại bỏ các giá trị chính không thể tạo ra bất kỳ hàng tham gia nào. (Ngoài ra không có gì đang được cập nhật)
Truy vấn
không được tối ưu hóa Kế hoạch của truy vấn không được tối ưu hóa không có tính tương đồng, sử dụng phép nối vòng lặp lồng nhau và cần thực hiện lọc IO dư trên các bản ghi 550M. (Ngoài ra bản cập nhật đang diễn ra)
Bạn có thể làm gì để cải thiện truy vấn không được tối ưu hóa?
Thay đổi chỉ mục để có First_name & last_name trong danh sách cột chính:
TẠO INDEX IX_largeTableOfP People_birth_date_first_name_last_name trên dbo.largeTableOfP People (birthday_date, First_name, last_name) bao gồm (id)
Nhưng do việc sử dụng các hàm và bảng này lớn nên đây có thể không phải là giải pháp tối ưu.
- Cập nhật số liệu thống kê, sử dụng biên dịch lại để thử và có được kế hoạch tốt hơn.
- Thêm TÙY CHỌN
(HASH JOIN, MERGE JOIN)
vào truy vấn
- ...
Kiểm tra dữ liệu + Truy vấn được sử dụng
CREATE TABLE #smallTableOfPeople(importantValue int, birthDate datetime2, first_name varchar(50),last_name varchar(50));
CREATE TABLE #largeTableOfPeople(importantValue int, birth_date datetime2, first_name varchar(50),last_name varchar(50));
set nocount on;
DECLARE @i int = 1
WHILE @i <= 1000
BEGIN
insert into #smallTableOfPeople (importantValue,birthDate,first_name,last_name)
VALUES(NULL, dateadd(mi,@i,'2018-01-18 11:05:29.067'),'Frodo','Baggins');
set @i += 1;
END
set nocount on;
DECLARE @j int = 1
WHILE @j <= 20000
BEGIN
insert into #largeTableOfPeople (importantValue,birth_Date,first_name,last_name)
VALUES(@j, dateadd(mi,@j,'2018-01-18 11:05:29.067'),'Frodo','Baggins');
set @j += 1;
END
SET STATISTICS IO, TIME ON;
SELECT smallTbl.importantValue , largeTbl.importantValue
FROM #smallTableOfPeople smallTbl
JOIN #largeTableOfPeople largeTbl
ON largeTbl.birth_date = smallTbl.birthDate
AND DIFFERENCE(RTRIM(LTRIM(smallTbl.last_name)),RTRIM(LTRIM(largeTbl.last_name))) = 4
AND DIFFERENCE(RTRIM(LTRIM(smallTbl.first_name)),RTRIM(LTRIM(largeTbl.first_name))) = 4
WHERE smallTbl.importantValue IS NULL
-- The following line is "the optimization"
AND LEFT(RTRIM(LTRIM(largeTbl.last_name)), 1) IN ('a','à','á','b','c','d','e','è','é','f','g','h','i','j','k','l','m','n','o','ô','ö','p','q','r','s','t','u','ü','v','w','x','y','z','æ','ä','ø','å');
SELECT smallTbl.importantValue , largeTbl.importantValue
FROM #smallTableOfPeople smallTbl
JOIN #largeTableOfPeople largeTbl
ON largeTbl.birth_date = smallTbl.birthDate
AND DIFFERENCE(RTRIM(LTRIM(smallTbl.last_name)),RTRIM(LTRIM(largeTbl.last_name))) = 4
AND DIFFERENCE(RTRIM(LTRIM(smallTbl.first_name)),RTRIM(LTRIM(largeTbl.first_name))) = 4
WHERE smallTbl.importantValue IS NULL
-- The following line is "the optimization"
--AND LEFT(RTRIM(LTRIM(largeTbl.last_name)), 1) IN ('a','à','á','b','c','d','e','è','é','f','g','h','i','j','k','l','m','n','o','ô','ö','p','q','r','s','t','u','ü','v','w','x','y','z','æ','ä','ø','å')
drop table #largeTableOfPeople;
drop table #smallTableOfPeople;
AND LEFT(TRIM(largeTbl.last_name), 1) BETWEEN 'a' AND 'z' COLLATE LATIN1_GENERAL_CI_AI
nên làm những gì bạn muốn ở đó mà không yêu cầu bạn liệt kê tất cả các ký tự và có mã khó đọc