Tôi khá chắc chắn các định nghĩa bảng gần với điều này:
CREATE TABLE dbo.households
(
tempId integer NOT NULL,
n integer NOT NULL,
HHID integer IDENTITY NOT NULL,
CONSTRAINT [UQ dbo.households HHID]
UNIQUE NONCLUSTERED (HHID),
CONSTRAINT [PK dbo.households tempId, n]
PRIMARY KEY CLUSTERED (tempId, n)
);
CREATE TABLE dbo.persons
(
tempId integer NOT NULL,
sporder integer NOT NULL,
n integer NOT NULL,
PERID integer IDENTITY NOT NULL,
HHID integer NOT NULL,
CONSTRAINT [UQ dbo.persons HHID]
UNIQUE NONCLUSTERED (PERID),
CONSTRAINT [PK dbo.persons tempId, n, sporder]
PRIMARY KEY CLUSTERED (tempId, n, sporder)
);
Tôi không có số liệu thống kê cho các bảng này hoặc dữ liệu của bạn, nhưng ít nhất những điều sau đây sẽ đặt chính xác số lượng bảng (số trang là một phỏng đoán):
UPDATE STATISTICS dbo.persons
WITH
ROWCOUNT = 5239842,
PAGECOUNT = 100000;
UPDATE STATISTICS dbo.households
WITH
ROWCOUNT = 1928783,
PAGECOUNT = 25000;
Phân tích kế hoạch truy vấn
Truy vấn bạn có bây giờ là:
UPDATE P
SET HHID = H.HHID
FROM dbo.households AS H
JOIN dbo.persons AS P
ON P.tempId = H.tempId
AND P.n = H.n;
Điều này tạo ra kế hoạch khá kém hiệu quả:
Các vấn đề chính trong kế hoạch này là tham gia băm và sắp xếp. Cả hai đều yêu cầu cấp bộ nhớ (phép nối băm cần xây dựng bảng băm và sắp xếp cần có chỗ để lưu trữ các hàng trong khi sắp xếp tiến trình). Plan Explorer cho thấy truy vấn này đã được cấp 765 MB:
Đây là khá nhiều bộ nhớ máy chủ để dành cho một truy vấn! Hơn nữa, việc cấp bộ nhớ này được cố định trước khi bắt đầu thực hiện dựa trên ước tính kích thước và số lượng hàng.
Nếu bộ nhớ hóa ra không đủ trong thời gian thực hiện, ít nhất một số dữ liệu cho hàm băm và / hoặc sắp xếp sẽ được ghi vào đĩa tempdb vật lý . Điều này được gọi là 'tràn' và nó có thể là một hoạt động rất chậm. Bạn có thể theo dõi các sự cố tràn này (trong SQL Server 2008) bằng cách sử dụng các sự kiện Profiler Hash Cảnh báo và Sắp xếp cảnh báo .
Ước tính cho đầu vào xây dựng của bảng băm là rất tốt:
Ước tính cho đầu vào sắp xếp ít chính xác hơn:
Bạn sẽ phải sử dụng Profiler để kiểm tra, nhưng tôi nghi ngờ loại này sẽ tràn sang tempdb trong trường hợp này. Cũng có thể bảng băm tràn ra, nhưng điều đó ít rõ ràng hơn.
Lưu ý rằng bộ nhớ dành riêng cho truy vấn này được phân chia giữa bảng băm và sắp xếp, vì chúng chạy đồng thời. Thuộc tính gói Phân số bộ nhớ hiển thị số lượng tương đối của cấp bộ nhớ dự kiến sẽ được sử dụng cho mỗi thao tác.
Tại sao Sắp xếp và Hash?
Sắp xếp được giới thiệu bởi trình tối ưu hóa truy vấn để đảm bảo rằng các hàng đến toán tử Cập nhật chỉ mục cụm theo thứ tự khóa cụm. Điều này thúc đẩy truy cập tuần tự vào bảng, thường hiệu quả hơn nhiều so với truy cập ngẫu nhiên.
Phép nối băm là một lựa chọn ít rõ ràng hơn, bởi vì đầu vào của nó có kích thước tương tự (dù sao cũng là xấp xỉ đầu tiên). Tham gia băm là tốt nhất trong đó một đầu vào (đầu vào xây dựng bảng băm) tương đối nhỏ.
Trong trường hợp này, mô hình chi phí của trình tối ưu hóa xác định rằng phép nối băm rẻ hơn trong ba tùy chọn (hàm băm, hợp nhất, vòng lặp lồng nhau).
Cải thiện hiệu suất
Mô hình chi phí không phải lúc nào cũng đúng. Nó có xu hướng ước tính quá mức chi phí tham gia hợp nhất song song, đặc biệt là khi số lượng chủ đề tăng lên. Chúng tôi có thể buộc tham gia hợp nhất với một gợi ý truy vấn:
UPDATE P
SET HHID = H.HHID
FROM dbo.households AS H
JOIN dbo.persons AS P
ON P.tempId = H.tempId
AND P.n = H.n
OPTION (MERGE JOIN);
Điều này tạo ra một gói không yêu cầu nhiều bộ nhớ (vì hợp nhất không cần bảng băm):
Sắp xếp có vấn đề vẫn còn đó, bởi vì hợp nhất chỉ giữ nguyên thứ tự của các khóa tham gia của nó (tempId, n) nhưng các khóa được nhóm là (tempId, n, sporder). Bạn có thể thấy kế hoạch hợp nhất thực hiện không tốt hơn kế hoạch tham gia băm.
Vòng lặp lồng nhau Tham gia
Chúng ta cũng có thể thử tham gia một vòng lặp lồng nhau:
UPDATE P
SET HHID = H.HHID
FROM dbo.households AS H
JOIN dbo.persons AS P
ON P.tempId = H.tempId
AND P.n = H.n
OPTION (LOOP JOIN);
Kế hoạch cho truy vấn này là:
Kế hoạch truy vấn này được coi là tồi tệ nhất bởi mô hình chi phí của trình tối ưu hóa, nhưng nó có một số tính năng rất đáng mong đợi. Đầu tiên, các vòng lặp lồng nhau không yêu cầu cấp bộ nhớ. Thứ hai, nó có thể duy trì thứ tự khóa từ Persons
bảng để không cần sắp xếp rõ ràng. Bạn có thể thấy kế hoạch này thực hiện tương đối tốt, thậm chí có thể đủ tốt.
Vòng lặp song song lồng nhau
Hạn chế lớn với kế hoạch các vòng lặp lồng nhau là nó chạy trên một luồng duy nhất. Có khả năng truy vấn này được hưởng lợi từ tính song song, nhưng trình tối ưu hóa quyết định không có lợi thế nào khi thực hiện điều đó ở đây. Điều này cũng không hẳn đúng. Thật không may, không có gợi ý truy vấn tích hợp để có kế hoạch song song, nhưng có một cách không có giấy tờ:
UPDATE t1
SET t1.HHID = t2.HHID
FROM dbo.persons AS t1
INNER JOIN dbo.households AS t2
ON t1.tempId = t2.tempId AND t1.n = t2.n
OPTION (LOOP JOIN, QUERYTRACEON 8649);
Kích hoạt cờ theo dõi 8649 với QUERYTRACEON
gợi ý tạo ra kế hoạch này:
Bây giờ chúng tôi có một kế hoạch tránh sắp xếp, không yêu cầu thêm bộ nhớ để tham gia và sử dụng song song một cách hiệu quả. Bạn sẽ tìm thấy truy vấn này thực hiện tốt hơn nhiều so với các lựa chọn thay thế.
Thông tin thêm về tính song song trong bài viết của tôi Buộc Kế hoạch thực hiện truy vấn song song :