Tôi có 3 bảng "lớn" tham gia trên một cặp cột (cả hai int
).
- Bảng 1 có ~ 200 triệu hàng
- Bảng 2 có ~ 1,5 triệu hàng
- Bảng 3 có ~ 6 triệu hàng
Mỗi bảng có một nhóm chỉ số trên Key1
, Key2
và sau đó thêm một cột. Key1
có cardinality thấp và rất sai lệch. Nó luôn được tham chiếu trong WHERE
mệnh đề. Key2
không bao giờ được đề cập trong WHERE
mệnh đề. Mỗi tham gia là nhiều-nhiều.
Vấn đề là với ước tính cardinality. Ước tính đầu ra của mỗi liên kết trở nên nhỏ hơn thay vì lớn hơn . Điều này dẫn đến ước tính cuối cùng là hàng trăm thấp khi kết quả thực tế là hàng triệu.
Có cách nào để tôi đầu mối CE để ước tính tốt hơn không?
SELECT 1
FROM Table1 t1
JOIN Table2 t2
ON t1.Key1 = t2.Key1
AND t1.Key2 = t2.Key2
JOIN Table3 t3
ON t1.Key1 = t3.Key1
AND t1.Key2 = t3.Key2
WHERE t1.Key1 = 1;
Các giải pháp tôi đã thử:
- Tạo số liệu thống kê nhiều cột trên
Key1
,Key2
- Tạo hàng tấn số liệu thống kê được lọc trên
Key1
(Điều này giúp khá nhiều, nhưng tôi kết thúc với hàng ngàn số liệu thống kê do người dùng tạo trong cơ sở dữ liệu.)
Kế hoạch thực hiện đeo mặt nạ (xin lỗi vì mặt nạ xấu)
Trong trường hợp tôi đang xem xét, kết quả có 9 triệu hàng. CE mới ước tính 180 hàng; di sản CE ước tính 6100 hàng.
Đây là một ví dụ có thể tái tạo:
DROP TABLE IF EXISTS #Table1, #Table2, #Table3;
CREATE TABLE #Table1 (Key1 INT NOT NULL, Key2 INT NOT NULL, T1Key3 INT NOT NULL, CONSTRAINT pk_t1 PRIMARY KEY CLUSTERED (Key1, Key2, T1Key3));
CREATE TABLE #Table2 (Key1 INT NOT NULL, Key2 INT NOT NULL, T2Key3 INT NOT NULL, CONSTRAINT pk_t2 PRIMARY KEY CLUSTERED (Key1, Key2, T2Key3));
CREATE TABLE #Table3 (Key1 INT NOT NULL, Key2 INT NOT NULL, T3Key3 INT NOT NULL, CONSTRAINT pk_t3 PRIMARY KEY CLUSTERED (Key1, Key2, T3Key3));
-- Table1
WITH Numbers
AS (SELECT TOP (1000000) Number = ROW_NUMBER() OVER(ORDER BY t1.number)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2),
DataSize (Key1, NumberOfRows)
AS (SELECT 1, 2000 UNION
SELECT 2, 10000 UNION
SELECT 3, 25000 UNION
SELECT 4, 50000 UNION
SELECT 5, 200000)
INSERT INTO #Table1
SELECT Key1
, Key2 = ROW_NUMBER() OVER (PARTITION BY Key1, T1Key3 ORDER BY Number)
, T1Key3
FROM DataSize
CROSS APPLY (SELECT TOP(NumberOfRows)
Number
, T1Key3 = Number%(Key1*Key1) + 1
FROM Numbers
ORDER BY Number) size;
-- Table2 (same Key1, Key2 values; smaller number of distinct third Key)
WITH Numbers
AS (SELECT TOP (1000000) Number = ROW_NUMBER() OVER(ORDER BY t1.number)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2)
INSERT INTO #Table2
SELECT DISTINCT
Key1
, Key2
, T2Key3
FROM #Table1
CROSS APPLY (SELECT TOP (Key1*10)
T2Key3 = Number
FROM Numbers
ORDER BY Number) size;
-- Table2 (same Key1, Key2 values; smallest number of distinct third Key)
WITH Numbers
AS (SELECT TOP (1000000) Number = ROW_NUMBER() OVER(ORDER BY t1.number)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2)
INSERT INTO #Table3
SELECT DISTINCT
Key1
, Key2
, T3Key3
FROM #Table1
CROSS APPLY (SELECT TOP (Key1)
T3Key3 = Number
FROM Numbers
ORDER BY Number) size;
DROP TABLE IF EXISTS #a;
SELECT col = 1
INTO #a
FROM #Table1 t1
JOIN #Table2 t2
ON t1.Key1 = t2.Key1
AND t1.Key2 = t2.Key2
WHERE t1.Key1 = 1;
DROP TABLE IF EXISTS #b;
SELECT col = 1
INTO #b
FROM #Table1 t1
JOIN #Table2 t2
ON t1.Key1 = t2.Key1
AND t1.Key2 = t2.Key2
JOIN #Table3 t3
ON t1.Key1 = t3.Key1
AND t1.Key2 = t3.Key2
WHERE t1.Key1 = 1;
make_parallel
Chức năng của Adam được sử dụng để giúp giảm thiểu vấn đề. Tôi sẽ xem xétmany
. Có vẻ như một hỗ trợ ban nhạc khá thô.