TL; DR
เนื่องจากคำถามนี้ยังคงได้รับการดูฉันจะสรุปได้ที่นี่เพื่อให้ผู้มาใหม่ไม่ต้องทนทุกข์กับประวัติศาสตร์:
JOIN table t ON t.member = @value1 OR t.member = @value2 -- this is slow as hell
JOIN table t ON t.member = COALESCE(@value1, @value2) -- this is blazing fast
-- Note that here if @value1 has a value, @value2 is NULL, and vice versa
ฉันรู้ว่านี่อาจไม่ใช่ปัญหาของทุกคน แต่การเน้นความไวของอนุประโยค ON อาจช่วยให้คุณมองไปในทิศทางที่ถูกต้อง ไม่ว่าในกรณีใดข้อความต้นฉบับอยู่ที่นี่สำหรับนักมานุษยวิทยาในอนาคต:
ข้อความต้นฉบับ
พิจารณาแบบสอบถามแบบง่าย ๆ ต่อไปนี้ (มีเพียง 3 ตารางที่เกี่ยวข้อง)
SELECT
l.sku_id AS ProductId,
l.is_primary AS IsPrimary,
v1.category_name AS Category1,
v2.category_name AS Category2,
v3.category_name AS Category3,
v4.category_name AS Category4,
v5.category_name AS Category5
FROM category c4
JOIN category_voc v4 ON v4.category_id = c4.category_id and v4.language_code = 'en'
JOIN category c3 ON c3.category_id = c4.parent_category_id
JOIN category_voc v3 ON v3.category_id = c3.category_id and v3.language_code = 'en'
JOIN category c2 ON c2.category_id = c3.category_id
JOIN category_voc v2 ON v2.category_id = c2.category_id and v2.language_code = 'en'
JOIN category c1 ON c1.category_id = c2.parent_category_id
JOIN category_voc v1 ON v1.category_id = c1.category_id and v1.language_code = 'en'
LEFT OUTER JOIN category c5 ON c5.parent_category_id = c4.category_id
LEFT OUTER JOIN category_voc v5 ON v5.category_id = c5.category_id and v5.language_code = @lang
JOIN category_link l on l.sku_id IN (SELECT value FROM #Ids) AND
(
l.category_id = c4.category_id OR
l.category_id = c5.category_id
)
WHERE c4.[level] = 4 AND c4.version_id = 5
นี่เป็นข้อความค้นหาที่ค่อนข้างง่ายส่วนที่สับสนเพียงอย่างเดียวคือการเข้าร่วมหมวดหมู่สุดท้ายด้วยวิธีนี้เนื่องจากหมวดหมู่ระดับ 5 อาจมีหรือไม่มีอยู่ ในตอนท้ายของการสืบค้นฉันกำลังมองหาข้อมูลหมวดหมู่ต่อรหัสผลิตภัณฑ์ (SKU ID) และนั่นคือสิ่งที่ table_link ของตารางที่มีขนาดใหญ่มากเข้ามาในที่สุดตาราง #Ids เป็นเพียงตารางชั่วคราวที่มี 10'000 Ids
เมื่อดำเนินการฉันจะได้รับแผนการดำเนินการตามจริง:
อย่างที่คุณเห็นเวลาเกือบ 90% ใช้เวลาในวงซ้อนกัน (Inner Join) นี่คือข้อมูลเพิ่มเติมเกี่ยวกับลูปซ้อนกัน:
โปรดทราบว่าชื่อตารางไม่ตรงกันทั้งหมดเนื่องจากฉันแก้ไขชื่อตารางแบบสอบถามเพื่อให้สามารถอ่านได้ แต่มันค่อนข้างง่ายที่จะจับคู่ (ads_alt_category = หมวดหมู่) มีวิธีใดที่จะเพิ่มประสิทธิภาพการค้นหานี้หรือไม่ โปรดทราบว่าในการผลิตตาราง temp #Ids ไม่มีอยู่มันเป็นพารามิเตอร์ที่มีมูลค่าของตารางที่มี 10'000 Ids เดียวกันส่งต่อไปยังกระบวนงานที่เก็บไว้
ข้อมูลเพิ่มเติม:
- ดัชนีหมวดหมู่ใน category_id และ parent_category_id
- category_voc ดัชนีใน category_id, language_code
- ดัชนี category_link บน sku_id, category_id
แก้ไข (แก้ไข)
ตามที่ระบุโดยคำตอบที่ยอมรับแล้วปัญหาคือประโยค OR ใน category_link JOIN อย่างไรก็ตามรหัสที่แนะนำในคำตอบที่ยอมรับนั้นช้ามากช้ากว่ารหัสต้นฉบับ วิธีแก้ปัญหาที่เร็วกว่าและสะอาดกว่าคือการแทนที่เงื่อนไข JOIN ปัจจุบันด้วยวิธีต่อไปนี้:
JOIN category_link l on l.sku_id IN (SELECT value FROM @p1) AND l.category_id = COALESCE(c5.category_id, c4.category_id)
การปรับแต่งนาทีนี้เป็นวิธีที่เร็วที่สุดทดสอบกับการเข้าร่วมสองครั้งจากคำตอบที่ยอมรับและทดสอบกับ CROSS APPLY ตามที่แนะนำโดย valverij