ฉันมี 3 "ใหญ่" ตารางที่เข้าร่วมในคอลัมน์ (ทั้งสองint
)
- ตารางที่ 1 มีประมาณ 200 ล้านแถว
- ตารางที่ 2 มีประมาณ 1.5 ล้านแถว
- ตารางที่ 3 มีประมาณ 6 ล้านแถว
แต่ละตารางมีดัชนีคลัสเตอร์บนKey1
, Key2
และจากนั้นหนึ่งคอลัมน์อื่น ๆ Key1
มี cardinality ต่ำและเบ้มาก มันถูกอ้างอิงอยู่เสมอในWHERE
ข้อ Key2
ไม่เคยถูกกล่าวถึงในWHERE
ข้อ การเข้าร่วมแต่ละครั้งมีหลายต่อหลายคน
ปัญหาเกิดขึ้นจากการประมาณเชิงปริมาณ การประมาณผลลัพธ์ของการรวมแต่ละครั้งจะเล็กลงแทนที่จะใหญ่ขึ้น ซึ่งจะส่งผลในการประมาณการขั้นสุดท้ายของหลายร้อยต่ำเมื่อผลลัพธ์ที่แท้จริงเป็นล้าน
มีวิธีใดบ้างที่ฉันจะรู้ว่า CE เป็นตัวประมาณการที่ดีกว่า?
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;
วิธีแก้ปัญหาที่ฉันได้ลอง:
- สร้างสถิติหลายคอลัมน์ใน
Key1
,Key2
- สร้างตันสถิติกรองบน
Key1
(ซึ่งจะช่วยให้ไม่น้อย แต่ผมจบลงด้วยการพันของสถิติผู้ใช้สร้างขึ้นในฐานข้อมูล.)
แผนปฏิบัติการสวมหน้ากาก (ขออภัยสำหรับการปิดบังไม่ดี)
ในกรณีที่ฉันดูผลลัพธ์จะมี 9 ล้านแถว CE ใหม่ประมาณ 180 แถว มรดก CE ประมาณ 6100 แถว
นี่คือตัวอย่างที่ทำซ้ำได้:
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
ฟังก์ชั่นของอดัมเคยชินกับการช่วยบรรเทาปัญหาmany
ฉันจะมีลักษณะที่ ดูเหมือนว่าจะเป็นวงช่วยเหลือขั้นต้นสวย