TL; DR
Bu soru görüş almaya devam ettiğinden, burada özetleyeceğim, böylece yeni gelenler tarihe katlanmak zorunda kalmayacaklar:
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
Bunun herkesin sorunu olmayabilir ama ON cümlelerinin hassasiyetini vurgulayarak doğru yöne bakmanıza yardımcı olabilir. Her durumda, orijinal metin gelecek antropologlar için burada:
Orjinal metin
Aşağıdaki basit sorguyu düşünün (yalnızca 3 tablo dahil)
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
Bu oldukça basit bir sorgu, sadece kafa karıştırıcı olan bölüm son kategori birleşimidir, bu şekildedir, çünkü kategori 5 seviyesi var olabilir veya olmayabilir. Sorgunun sonunda, ürün kimliği (SKU ID) başına kategori bilgisi arıyorum ve bu, çok büyük bir tablo category_link'in bulunduğu yerdir. Son olarak, #Ids tablosu yalnızca 10.000 Ids içeren geçici bir tablodur.
Yürütüldüğünde, aşağıdaki gerçek yürütme planını alıyorum:
Gördüğünüz gibi zamanın neredeyse% 90'ı İç İçe Döngüler (İç Birleştirme) içinde geçirilir. İşte bu Yuvalanmış Döngüler hakkında ek bilgi:
Tablo adlarının okunabilirlik için sorgu tablosu adlarını düzenlediğim için tam olarak eşleşmediğini, ancak eşleşmesinin oldukça kolay olduğunu unutmayın (ads_alt_category = category). Bu sorguyu optimize etmenin bir yolu var mı? Ayrıca, üretimde, #Ids temp tablosunun bulunmadığını, aynı 10'000 ID'nin Stored Prosedürüne iletilen bir Tablo Değerli Parametresinin olmadığını unutmayın.
İlave bilgi:
- category_id ve parent_category_id üzerindeki kategori endeksleri
- category_id, language_code üzerinde index_voc dizini
- sku_id, category_id üzerindeki category_link dizini
Düzenle (çözüldü)
Kabul edilen cevabın da belirttiği gibi, sorun kategorideki JOIN kategorisindeki OR cümlecikiydi. Ancak, kabul edilen cevapta önerilen kod çok yavaş, orijinal koddan bile daha yavaştır. Çok daha hızlı ve daha temiz bir çözüm, mevcut JOIN koşulunu aşağıdaki şekilde değiştirmek içindir:
JOIN category_link l on l.sku_id IN (SELECT value FROM @p1) AND l.category_id = COALESCE(c5.category_id, c4.category_id)
Bu dakika ayarlaması, en hızlı çözümdür, kabul edilen yanıttan çift birleştirmeye karşı test edilmiştir ve valverij tarafından önerildiği gibi ÇAPRAZ BAŞVURUSU'na karşı da test edilmiştir.