????????在 SQL 優化中,一般遵循**“非必要不使用子查詢”**的原則,因為子查詢可能會帶來額外的計算開銷,影響查詢效率。但是,并不是所有子查詢都需要避免,有時子查詢是最優解,具體要根據實際場景選擇合適的優化方式。
1、為什么盡量避免子查詢?
-
子查詢可能執行多次
-
非相關子查詢(Non-correlated subquery) 執行一次
-
相關子查詢(Correlated subquery) 可能要對每一行都執行一次,嚴重影響性能
-
-
索引可能無法生效
-
子查詢的結果通常存儲在臨時表中,可能導致索引失效
-
-
可能引入不必要的計算
-
許多子查詢可以通過
JOIN
或EXISTS
替代,避免重復計
-
2、如何優化?
(1)使用子查詢
????????例:
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);
?????????這條SQL中,子查詢會遍歷 orders
表的所有數據,然后再匹配 users
表,可能導致性能下降。
?????????優化(使用 JOIN
):
SELECT DISTINCT users.*
FROM users
JOIN orders ON users.id = orders.user_id;
????????避免了子查詢的重復執行,直接連接兩個表,提高查詢效率。
(2)使用 IN
子查詢
????????例:
SELECT * FROM products
WHERE category_id IN (SELECT id FROM categories WHERE name = 'Electronics');
????????子查詢會先獲取 id
列,再在 products
表中查找,可能導致索引失效。?
????????優化(使用 JOIN
):
SELECT p.* FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.name = 'Electronics';
????????JOIN 讓查詢引擎直接連接表,而不是單獨計算子查詢,提高查詢速度。
(3)使用 NOT IN
????????例:
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders);
? NOT IN
可能導致索引失效,并且當 orders.user_id
里有 NULL
值時,查詢結果可能不正確。
? ? ? ? 優化(NOT EXISTS
):
SELECT * FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-
NOT EXISTS
通常比NOT IN
更高效,因為它在找到匹配的記錄時就會停止搜索,而NOT IN
需要計算整個子查詢結果。 -
避免
NULL
值帶來的問題
3、什么時候可以使用子查詢??
????????雖然子查詢通常會帶來性能問題,但在某些情況下是合理的。
? ? ?(1)子查詢返回的結果是一個固定值(如 MAX()
、MIN()
)
? ? ?(2)子查詢無法用 JOIN
代替(如分組統計場景)
? ? ?(3)業務邏輯復雜,避免 JOIN
使 SQL 變得過于復雜。
???????例如:?
SELECT name, price FROM products
WHERE price = (SELECT MAX(price) FROM products WHERE category_id = products.category_id);
????????這種情況下,子查詢返回的是單個值,對性能影響較小。
4、總結
(1)可以優化子查詢的場景:
-
IN
子查詢 →JOIN
-
NOT IN
子查詢 →NOT EXISTS
-
相關子查詢 →
JOIN
結合GROUP BY
(2)適合使用子查詢的情況
-
需要計算單個聚合值(如
MAX()
、SUM()
) -
業務邏輯導致
JOIN
過于復雜
以上就是關于子查詢的相關使用策略!?