TL; DR
Vì câu hỏi này tiếp tục nhận được lượt xem, tôi sẽ tóm tắt nó ở đây để những người mới không phải chịu đựng lịch sử:
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
Tôi nhận ra đây có thể không phải là vấn đề của mọi người, nhưng bằng cách làm nổi bật độ nhạy của các mệnh đề ON, nó có thể giúp bạn nhìn đúng hướng. Trong mọi trường hợp, văn bản gốc có ở đây cho các nhà nhân học trong tương lai:
Văn bản gốc
Hãy xem xét các truy vấn đơn giản sau đây (chỉ có 3 bảng liên quan)
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
Đây là một truy vấn khá đơn giản, phần khó hiểu duy nhất là tham gia danh mục cuối cùng, theo cách này vì loại 5 có thể tồn tại hoặc không tồn tại. Ở cuối truy vấn tôi đang tìm kiếm thông tin danh mục cho mỗi ID sản phẩm (ID SKU) và đó là nơi mà bảng_link rất lớn xuất hiện. Cuối cùng, bảng #Ids chỉ là một bảng tạm thời chứa 10.000 Id.
Khi được thực thi, tôi nhận được kế hoạch thực hiện thực tế sau đây:
Như bạn có thể thấy, gần 90% thời gian được dành cho các Vòng lặp lồng nhau (Tham gia bên trong). Dưới đây là thông tin thêm về các vòng lặp lồng nhau:
Lưu ý rằng tên bảng không khớp chính xác vì tôi đã chỉnh sửa tên bảng truy vấn để dễ đọc, nhưng nó khá dễ khớp (ads_alt_carget = category). Có cách nào để tối ưu hóa truy vấn này? Cũng lưu ý rằng trong sản xuất, bảng tạm thời #Ids không tồn tại, đó là Thông số có giá trị của Bảng trong cùng 10.000.000 Id được chuyển cho Quy trình được lưu trữ.
Thông tin bổ sung:
- các chỉ mục danh mục trên category_id và Parent_carget_id
- chỉ mục category_voc trên category_id, ngôn ngữ_code
- index_link index trên sku_id, category_id
Chỉnh sửa (đã giải quyết)
Như được chỉ ra bởi câu trả lời được chấp nhận, vấn đề là mệnh đề OR trong category_link THAM GIA. Tuy nhiên, mã được đề xuất trong câu trả lời được chấp nhận là rất chậm, chậm hơn cả mã gốc. Một giải pháp nhanh hơn và cũng sạch hơn nhiều chỉ đơn giản là thay thế điều kiện THAM GIA hiện tại bằng cách sau:
JOIN category_link l on l.sku_id IN (SELECT value FROM @p1) AND l.category_id = COALESCE(c5.category_id, c4.category_id)
Điều chỉnh phút này là giải pháp nhanh nhất, được thử nghiệm đối với phép nối kép từ câu trả lời được chấp nhận và cũng được thử nghiệm với CROSS ỨNG DỤNG theo đề xuất của valverij.