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が存在する場合と存在しない場合があるため、この方法です。クエリの最後に、製品ID(SKU ID)ごとのカテゴリ情報を探しています。そこが非常に大きなテーブルcategory_linkの出番です。最後に、テーブル#Idsは、10'000 IDを含む一時テーブルです。
実行すると、次の実際の実行計画が得られます。
ご覧のとおり、時間のほぼ90%がネストされたループ(内部結合)に費やされています。これらのネストされたループに関する追加情報は次のとおりです。
読みやすいようにクエリテーブル名を編集したため、テーブル名は完全には一致しませんが、一致させるのは非常に簡単です(ads_alt_category = category)。このクエリを最適化する方法はありますか?本番環境では、一時テーブル#Idsは存在せず、ストアドプロシージャに渡される同じ10'000 IDのテーブル値パラメーターであることに注意してください。
追加情報:
- category_idおよびparent_category_idのカテゴリインデックス
- category_id、language_codeのcategory_vocインデックス
- sku_id、category_idのcategory_linkインデックス
編集(解決済み)
受け入れられた回答で指摘されているように、問題はcategory_link JOINのOR句でした。ただし、受け入れられた回答で提案されたコードは非常に遅く、元のコードよりも遅くなります。はるかに高速でクリーンなソリューションは、現在の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)
この微調整は最速のソリューションであり、承認された回答からの二重結合に対してテストされ、valverijが提案するCROSS APPLYに対してもテストされています。