萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 變數技巧:用自定義變量優化 UNION 短路查詢

問題背景

需求:優先查詢 users 表,找到即返回;未找到才查詢 users_archived。普通 UNION ALL 會掃描兩表,造成不必要開銷。

優化寫法:用戶變量短路

SELECT GREATEST(@found := -1, id) AS id, 'users' AS src_table
FROM users WHERE id = 1
UNION ALL
SELECT id, 'users_archived'
FROM users_archived WHERE id = 1 AND @found IS NULL
UNION ALL
SELECT 1, 'reset'
FROM DUAL WHERE (@found := NULL) IS NOT NULL;

執行邏輯解析

  1. 第一分支:@found := -1 賦值為 -1 (非 NULL),GREATEST(-1, id) 回傳 id,@found 變為 -1。
  2. 第二分支:WHERE ... AND @found IS NULL 因 @found=-1 不滿足,直接跳過,不掃描 users_archived。
  3. 第三分支:(@found := NULL) IS NOT NULL 永遠為 FALSE(賦值結果為 NULL),不產生資料,但完成 @found 重置為 NULL,供下次查詢使用。

關鍵點

  • GREATEST / LEAST 可在 SELECT 列表中執行賦值並回傳業務值,避免額外欄位。
  • 用戶變量 @var 為會話級,連線斷開自動釋放,無汙染風險。
  • DUAL 為虛擬表,配合 WHERE FALSE 達成「僅執行副作用」目的。

適用場景與限制

  • 適用:兩表互斥、優先順序固定、單鍵值查詢。
  • 不適用:需合併兩表結果、複雜 JOIN、分頁查詢。
  • MySQL 8.0+ 建議改用 CTE + UNION ALL + LIMIT 1,可讀性更高:
    WITH first_match AS (
        SELECT id, 'users' AS src FROM users WHERE id = 1
        UNION ALL
        SELECT id, 'users_archived' FROM users_archived WHERE id = 1
    )
    SELECT * FROM first_match LIMIT 1;

延伸:動態 SQL 構建

若優先順序可配置,應用層拼接 SQL 或存儲過程動態構建上述 UNION 結構。

copyright © 萬盛學電腦網 all rights reserved