Trong bài trước của tôi, tôi đã nói về các cách tạo một dãy số liền nhau từ 1 đến 1.000. Bây giờ tôi muốn nói về các cấp độ tiếp theo của quy mô:tạo ra các bộ số 50.000 và 1.000.000.
Tạo bộ 50.000 số
Khi bắt đầu loạt bài này, tôi thực sự tò mò làm thế nào các phương pháp tiếp cận khác nhau sẽ mở rộng quy mô thành các bộ số lớn hơn. Cuối cùng, tôi hơi mất hứng khi thấy rằng cách tiếp cận yêu thích của tôi - sử dụng sys.all_objects
- không phải là phương pháp hiệu quả nhất. Nhưng các kỹ thuật khác nhau này sẽ mở rộng quy mô thành 50.000 hàng như thế nào?
Bảng số
Vì chúng tôi đã tạo một bảng Numbers với 1.000.000 hàng, nên truy vấn này hầu như giống hệt nhau:
CHỌN ĐẦU (50000) n TỪ Dbo. SỐ LỆNH THEO n;
Kế hoạch:
spt_values
Vì chỉ có ~ 2.500 hàng trong spt_values
, chúng ta cần phải sáng tạo hơn một chút nếu muốn sử dụng nó làm nguồn của bộ tạo bộ của chúng ta. Một cách để mô phỏng một bảng lớn hơn là CROSS JOIN
nó chống lại chính nó. Nếu chúng tôi làm điều đó thô, chúng tôi sẽ kết thúc với ~ 2.500 hàng bình phương (hơn 6 triệu). Chỉ cần 50.000 hàng, chúng ta cần khoảng 224 hàng bình phương. Vì vậy, chúng tôi có thể làm điều này:
; WITH x AS (SELECT TOP (224) number FROM [master] .. spt_values) SELECT TOP (50000) n =ROW_NUMBER () OVER (ORDER BY x.number) FROM x CROSS JOIN x AS yORDER BY n;
Lưu ý rằng điều này tương đương với, nhưng ngắn gọn hơn, biến thể này:
SELECT TOP (50000) n =ROW_NUMBER () OVER (ORDER BY x.number) FROM (CHỌN HÀNG ĐẦU (224) số FROM [master] .. spt_values) AS xCROSS JOIN (CHỌN ĐẦU (224) số FROM [master ] .. spt_values) NHƯ YORDER BY n;
Trong cả hai trường hợp, kế hoạch trông như thế này:
sys.all_objects
Giống như spt_values
, sys.all_objects
không hoàn toàn đáp ứng yêu cầu 50.000 hàng của riêng chúng tôi, vì vậy chúng tôi sẽ cần thực hiện một CROSS JOIN
tương tự .
;; WITH x AS (SELECT TOP (224) [object_id] FROM sys.all_objects) SELECT TOP (50000) n =ROW_NUMBER () OVER (ORDER BY x. [object_id]) FROM x CROSS JOIN x AS y ORDER THEO n;
Kế hoạch:
CTE xếp chồng
Chúng tôi chỉ cần thực hiện một điều chỉnh nhỏ đối với CTE xếp chồng của mình để có được chính xác 50.000 hàng:
; WITH e1 (n) AS (CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1) , - 10e2 (n) AS (CHỌN 1 TỪ e1 CROSS JOIN e1 AS b), - 10 * 10e3 (n) AS (CHỌN 1 TỪ e2 CROSS JOIN e2 AS b), - 100 * 100e4 (n) AS (CHỌN 1 TỪ e3 THAM GIA CHÉO (CHỌN ĐẦU 5 n TỪ e1) NHƯ b) - 5 * 10000 CHỌN n =ROW_NUMBER () HẾT (LỆNH THEO n) TỪ e4 LỆNH THEO n;
Kế hoạch:
CTE đệ quy
Cần có một thay đổi ít quan trọng hơn nữa để có được 50.000 hàng từ CTE đệ quy của chúng tôi:thay đổi WHERE
mệnh đề thành 50.000 và thay đổi MAXRECURSION
tùy chọn về 0.
; WITH n (n) AS (CHỌN 1 ĐOÀN KẾT TẤT CẢ CHỌN n + 1 TỪ n TRONG ĐÓ n <50000) CHỌN n TỪ n ĐƠN HÀNG THEO nOPTION (MAXRECURSION 0);
Kế hoạch:
Trong trường hợp này, có một biểu tượng cảnh báo về loại - hóa ra, trên hệ thống của tôi, loại cần thiết để tràn sang tempdb. Bạn có thể không thấy sự cố tràn trên hệ thống của mình, nhưng đây phải là một cảnh báo về các tài nguyên cần thiết cho kỹ thuật này.
Hiệu suất
Như với bộ thử nghiệm cuối cùng, chúng tôi sẽ so sánh từng kỹ thuật, bao gồm bảng Numbers với cả bộ đệm lạnh và bộ nhớ cache ấm và cả được nén và không nén:
Thời gian chạy, tính bằng mili giây, để tạo 50.000 số liền kề
Để có hình ảnh tốt hơn, hãy loại bỏ CTE đệ quy, là một con chó hoàn toàn trong thử nghiệm này và làm sai lệch kết quả:
Thời gian chạy, tính bằng mili giây, để tạo 50.000 số liền kề (không bao gồm đệ quy CTE)
Ở 1.000 hàng, sự khác biệt giữa được nén và không được nén là rất nhỏ, vì truy vấn chỉ cần đọc 8 và 9 trang tương ứng. Ở 50.000 hàng, khoảng cách rộng hơn một chút:74 trang so với 113. Tuy nhiên, chi phí tổng thể của việc giải nén dữ liệu dường như lớn hơn mức tiết kiệm trong I / O. Vì vậy, ở 50.000 hàng, một bảng số không nén có vẻ là phương pháp hiệu quả nhất để tính ra một tập liền kề - tuy nhiên, phải thừa nhận rằng lợi thế là không đáng kể.
Tạo bộ 1.000.000 số
Mặc dù tôi không thể hình dung ra nhiều trường hợp sử dụng mà bạn cần một bộ số liền nhau lớn như vậy, nhưng tôi muốn đưa nó vào cho hoàn chỉnh và bởi vì tôi đã thực hiện một số quan sát thú vị ở quy mô này.
Bảng số
Không có gì ngạc nhiên ở đây, truy vấn của chúng tôi bây giờ là:
CHỌN HÀNG ĐẦU 1000000 n TỪ dbo. SỐ LỆNH THEO n;
TOP
không hoàn toàn cần thiết, nhưng đó chỉ vì chúng ta biết rằng bảng Numbers và kết quả mong muốn của chúng ta có cùng số hàng. Kế hoạch vẫn khá giống với các thử nghiệm trước:
spt_values
Để nhận CROSS JOIN
tạo ra 1.000.000 hàng, chúng tôi cần lấy bình phương 1.000 hàng:
; WITH x AS (SELECT TOP (1000) number FROM [master] .. spt_values) SELECT n =ROW_NUMBER () OVER (ORDER BY x.number) FROM x CROSS JOIN x AS y ORDER BY n;
Kế hoạch:
sys.all_objects
Một lần nữa, chúng ta cần tích chéo của 1.000 hàng:
; WITH x AS (SELECT TOP (1000) [object_id] FROM sys.all_objects) SELECT n =ROW_NUMBER () OVER (ORDER BY x. [object_id]) FROM x CROSS JOIN x AS y ORDER BY n;Kế hoạch:
CTE xếp chồng
Đối với CTE xếp chồng lên nhau, chúng ta chỉ cần kết hợp
CROSS JOIN
hơi khác một chút s để nhận được 1.000.000 hàng:; WITH e1 (n) AS (CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1 ĐOÀN THỂ TẤT CẢ CHỌN 1) , - 10e2 (n) AS (CHỌN 1 TỪ e1 CROSS JOIN e1 AS b), - 10 * 10e3 (n) AS (CHỌN 1 TỪ e1 CROSS JOIN e2 AS b), - 10 * 100e4 (n) AS (CHỌN 1 TỪ e3 CHÉO THAM GIA e3 NHƯ b) - 1000 * 1000 CHỌN n =ROW_NUMBER () HẾT (LỆNH THEO n) TỪ e4 LỆNH THEO n;Kế hoạch:
Ở kích thước hàng này, bạn có thể thấy rằng giải pháp CTE xếp chồng song song với nhau. Vì vậy, tôi cũng đã chạy một phiên bản với
MAXDOP 1
để có được hình dạng kế hoạch tương tự như trước đây và để xem liệu tính song song có thực sự hữu ích hay không:
CTE đệ quy
CTE đệ quy một lần nữa chỉ có một thay đổi nhỏ; chỉ
WHERE
mệnh đề cần thay đổi:; WITH n (n) AS (CHỌN 1 ĐOÀN KẾT TẤT CẢ CHỌN n + 1 TỪ n TRONG ĐÓ n <1000000) CHỌN n TỪ n ĐƠN HÀNG THEO nOPTION (MAXRECURSION 0);Kế hoạch:
Hiệu suất
Một lần nữa chúng ta thấy hiệu suất của CTE đệ quy rất kém:
Thời gian chạy, tính bằng mili giây, để tạo 1.000.000 số liền kềLoại bỏ yếu tố ngoại lệ đó khỏi biểu đồ, chúng tôi sẽ có bức tranh tốt hơn về hiệu suất:
Thời gian chạy, tính bằng mili giây, để tạo 1.000.000 số liền kề (không bao gồm đệ quy CTE)Mặc dù một lần nữa, chúng ta thấy bảng Numbers không nén (ít nhất là với bộ đệm ấm) là bảng chiến thắng, nhưng sự khác biệt ngay cả ở thang điểm này không phải là tất cả những gì đáng chú ý.
Còn tiếp…
Bây giờ chúng ta đã khám phá kỹ lưỡng một số phương pháp để tạo một chuỗi số, chúng ta sẽ chuyển sang ngày. Trong bài cuối cùng của loạt bài này, chúng ta sẽ xem xét việc xây dựng phạm vi ngày dưới dạng một tập hợp, bao gồm việc sử dụng bảng lịch và một số trường hợp sử dụng mà việc này có thể hữu ích.
[Phần 1 | Phần 2 | Phần 3]
Phụ lục:Số hàng
Bạn có thể không cố gắng tạo ra một số hàng chính xác; thay vào đó, bạn có thể chỉ muốn một cách đơn giản để tạo ra nhiều hàng. Sau đây là danh sách kết hợp các chế độ xem danh mục sẽ giúp bạn có được các số lượng hàng khác nhau nếu bạn chỉ cần
SELECT
không cóWHERE
mệnh đề. Lưu ý rằng những con số này sẽ phụ thuộc vào việc bạn đang sử dụng RTM hay gói dịch vụ (vì một số đối tượng hệ thống được thêm vào hoặc sửa đổi) và cả việc bạn có cơ sở dữ liệu trống không.
Nguồn | Số lượng hàng | ||
---|---|---|---|
SQL Server 2008 R2 | SQL Server 2012 | SQL Server 2014 | |
master..spt_values | 2.508 | 2,515 | 2,519 |
master..spt_values CROSS JOIN master..spt_values | 6.290.064 | 6.325.225 | 6.345.361 |
sys.all_objects | 1.990 | 2.089 | 2.165 |
sys.all_columns | 5,157 | 7.276 | 8.560 |
sys.all_objects CROSS THAM GIA sys.all_objects | 3.960.100 | 4.363.921 | 4.687.225 |
sys.all_objects CROSS THAM GIA sys.all_columns | 10.262.430 | 15.199.564 | 18.532.400 |
sys.all_columns CROSS THAM GIA sys.all_columns | 26.594.649 | 52,940,176 | 73.273.600 |
Bảng 1:Số hàng cho các truy vấn xem danh mục khác nhau