最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL中多條查詢結(jié)果縱向拼接(UNION/UNION?ALL)優(yōu)化指南

 更新時間:2026年07月24日 08:28:30   作者:detayun  
本文將帶你徹底搞懂UNION和UNION?ALL的核心差異、性能影響及常見陷阱,包括LIMIT失效、排序異常、跨表OR優(yōu)化等高階技巧,助你寫出高效SQL,避免線上事故

前言

在日常開發(fā)中,我們經(jīng)常需要把多條獨立SELECT查詢的結(jié)果上下堆疊合并,也就是縱向拼接。

很多人容易混淆兩個概念:

  • JOIN:橫向拼接,增加列;
  • UNION / UNION ALL:縱向拼接,增加行。

不少開發(fā)直接上手寫UNION,遇到大數(shù)據(jù)量直接觸發(fā)慢查詢;同時還有LIMIT失效、排序異常、索引無法利用、跨表OR改造等一系列踩坑點。

本文系統(tǒng)講解MySQL縱向拼接語法、底層差異、規(guī)范寫法、高頻陷阱以及線上最優(yōu)實踐。

一、什么是縱向拼接

  • 橫向拼接(JOIN):兩張表根據(jù)關(guān)聯(lián)字段左右合并,行數(shù)重組,字段增多。
  • 縱向拼接(UNION系列):把多條查詢結(jié)果上下堆疊,字段結(jié)構(gòu)保持一致,行數(shù)累加

示意圖通俗理解:

查詢A結(jié)果:
id | name
1  | 張三

查詢B結(jié)果:
id | name
2  | 李四

縱向拼接后:
id | name
1  | 張三
2  | 李四

二、基礎(chǔ)語法與強(qiáng)制約束

縱向拼接依靠兩個關(guān)鍵字:UNIONUNION ALL。

硬性規(guī)則(違反直接報錯)

  1. 每條子查詢列數(shù)量必須完全一致
  2. 對應(yīng)位置字段數(shù)據(jù)類型盡量兼容;
  3. 最終字段名稱由第一條SELECT決定,后續(xù)子查詢別名無效;
  4. 不推薦子查詢使用SELECT *,字段結(jié)構(gòu)變更會直接引發(fā)異常。

基礎(chǔ)示例:

-- 縱向拼接兩條查詢
SELECT id, username FROM `user` WHERE status = 1
UNION ALL
SELECT id, access_key FROM `app_key` WHERE status = 1;

三、UNION 和 UNION ALL核心區(qū)別(重中之重)

UNION

  1. 合并結(jié)果后自動全局去重;
  2. MySQL底層會創(chuàng)建臨時表、執(zhí)行排序比對重復(fù);
  3. 執(zhí)行計劃大概率出現(xiàn) Using temporary; Using filesort
  4. 性能較差,大數(shù)據(jù)量慎用。

UNION = UNION ALL + DISTINCT 全局去重

UNION ALL

  1. 直接原樣縱向拼接,不去重、不排序;
  2. 無臨時表、無全局排序開銷;
  3. 性能遠(yuǎn)高于UNION,優(yōu)先選用

直觀對比測試

存在重復(fù)數(shù)據(jù)場景:

-- UNION:自動剔除重復(fù)行
SELECT user_id FROM `user` WHERE username = 'demo'
UNION
SELECT user_id FROM `app_key` WHERE access_key = 'demo_key';

-- UNION ALL:保留全部記錄,包含重復(fù)
SELECT user_id FROM `user` WHERE username = 'demo'
UNION ALL
SELECT user_id FROM `app_key` WHERE access_key = 'demo_key';

四、業(yè)務(wù)需要去重該怎么寫?

不推薦:直接使用 UNION

推薦方案:UNION ALL + 外層DISTINCT

SELECT DISTINCT user_id FROM (
    SELECT user_id FROM `user` WHERE username = 'demo'
    UNION ALL
    SELECT user_id FROM `app_key` WHERE access_key = 'demo_key'
) t;

優(yōu)勢:優(yōu)化器可以自主選擇哈希去重,不一定強(qiáng)制排序,優(yōu)化空間更大,線上標(biāo)準(zhǔn)寫法。

五、高頻踩坑:LIMIT 與 ORDER BY 作用范圍

陷阱1:不加括號,LIMIT只會作用最后一條子查詢

錯誤寫法

SELECT id,username FROM `user` LIMIT 10
UNION ALL
SELECT id,access_key FROM `app_key` LIMIT 10;

MySQL理解:整體合并之后只取10行,不是兩條各自限制10條。

正確寫法:子查詢使用括號包裹

(SELECT id,username FROM `user` LIMIT 10)
UNION ALL
(SELECT id,access_key FROM `app_key` LIMIT 10);

陷阱2:子查詢內(nèi)ORDER BY默認(rèn)無效

單獨寫ORDER BY不會生效,只有搭配LIMIT時,括號內(nèi)排序才會執(zhí)行。

-- 內(nèi)部排序生效
(SELECT id,username FROM `user` ORDER BY create_time DESC LIMIT 5)
UNION ALL
(SELECT id,access_key FROM `app_key` ORDER BY create_time DESC LIMIT 5);

陷阱3:想要整體結(jié)果統(tǒng)一排序

把全部拼接結(jié)果作為子查詢,外層統(tǒng)一ORDER BY

SELECT * FROM (
    (SELECT id,username FROM `user` LIMIT 10)
    UNION ALL
    (SELECT id,access_key FROM `app_key` LIMIT 10)
) t
ORDER BY id DESC;

六、經(jīng)典業(yè)務(wù)場景:跨表OR條件優(yōu)化(實戰(zhàn)高頻)

原始問題SQL(性能差、邏輯存在隱患)

SELECT t1.id,t1.username
FROM `user` t1
LEFT JOIN `app_key` t2 ON t1.id = t2.user_id
WHERE t1.username = 'demo' OR t2.access_key = 'demo_key';

這類LEFT JOIN + OR跨表條件極易索引失效。

標(biāo)準(zhǔn)優(yōu)化手段:拆分查詢,UNION ALL縱向拼接

-- 場景1:匹配用戶表賬號
SELECT id, username FROM `user` WHERE username = 'demo'

UNION ALL

-- 場景2:匹配密鑰表,關(guān)聯(lián)查詢用戶
SELECT t1.id, t1.username
FROM `user` t1
INNER JOIN `app_key` t2 ON t1.id = t2.user_id
WHERE t2.access_key = 'demo_key';

如需去重外層包DISTINCT,每條分支獨立執(zhí)行,能夠正常使用各自索引。

拓展:只需要查詢?nèi)我庖粭l匹配數(shù)據(jù)(短路查詢)

登錄、賬號檢索場景,找到第一條即可返回,減少掃描:

SELECT * FROM (
    (SELECT id, username FROM `user` WHERE username = 'demo' LIMIT 1)
    UNION ALL
    (SELECT t1.id, t1.username FROM `user` t1
     INNER JOIN `app_key` t2 ON t1.id = t2.user_id
     WHERE t2.access_key = 'demo_key' LIMIT 1)
) tmp LIMIT 1;

如果第一條分支命中,數(shù)據(jù)庫不需要繼續(xù)執(zhí)行第二條查詢。

七、縱向拼接編碼規(guī)范與優(yōu)化建議

  1. 優(yōu)先使用 UNION ALL,杜絕無條件使用 UNION;只有確認(rèn)必須全局去重時,使用UNION ALL + DISTINCT;
  2. 不要使用SELECT *,顯式指定字段,保證結(jié)構(gòu)穩(wěn)定;
  3. 子查詢需要限制行數(shù),必須用括號包裹;
  4. 多條分支查詢務(wù)必建立合適索引,縱向拼接不會提升單條子查詢性能;
  5. 分支數(shù)量不宜過多,過多子查詢可讀性變差,可以考慮應(yīng)用層多次查詢合并;
  6. 大數(shù)據(jù)場景避免上萬行結(jié)果拼接,網(wǎng)絡(luò)傳輸消耗較大;
  7. 不要依靠UNION實現(xiàn)單表內(nèi)部去重,單表去重直接使用DISTINCT

八、常見誤區(qū)匯總

誤區(qū)1:UNION一定比UNION ALL簡潔,少量數(shù)據(jù)無所謂

測試環(huán)境少量數(shù)據(jù)看不出差距;線上十萬級結(jié)果集,臨時表+排序會直接造成接口超時。

誤區(qū)2:WHERE條件寫在一起,不如UNION拼接靈活

很多跨表OR、復(fù)雜多條件檢索,拆分UNION ALL是唯一能穩(wěn)定走索引的方案。

誤區(qū)3:子查詢的字段別名全局生效

只有第一條SELECT的別名作為最終列名,后續(xù)子查詢別名會被忽略。

誤區(qū)4:UNION ALL內(nèi)部自動去重

不會,重復(fù)記錄會完整保留,必須手動處理。

九、驗證手段

使用EXPLAIN分析執(zhí)行計劃:

  • UNION:可見<union>、Using temporary、Using filesort
  • UNION ALL:執(zhí)行計劃簡潔,不存在全局臨時表與排序

十、全文總結(jié)

  1. MySQL縱向拼接依靠UNION / UNION ALL,作用是堆疊多行;橫向合并依靠JOIN,二者不要混淆;
  2. 性能鐵律:優(yōu)先 UNION ALL;需要去重采用 UNION ALL + DISTINCT,盡量避免直接UNION;
  3. LIMIT、ORDER BY作用范圍容易踩坑,子查詢增加括號控制作用域;
  4. LEFT JOIN + OR跨表條件慢查詢,首選方案:拆分為多條查詢,UNION ALL縱向拼接;
  5. 任何優(yōu)化的前提:每條獨立子查詢本身能夠正常命中索引。

日常開發(fā)牢記:縱向拼接只是結(jié)果合并手段,無法提升單條查詢掃描效率,優(yōu)化重心依然在每條分支SQL與索引設(shè)計。

以上就是MySQL中多條查詢結(jié)果縱向拼接(UNION/UNION ALL)優(yōu)化指南的詳細(xì)內(nèi)容,更多關(guān)于MySQL縱向拼接的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL數(shù)據(jù)庫卸載的完整步驟

    MySQL數(shù)據(jù)庫卸載的完整步驟

    這篇文章主要為大家詳細(xì)介紹了MySQL數(shù)據(jù)庫卸載的完整步驟,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • mysql獲取版本的幾種方法實現(xiàn)

    mysql獲取版本的幾種方法實現(xiàn)

    本文主要介紹了mysql獲取版本的方法實現(xiàn),主要介紹了三種方法,包含SELECT VERSION(),SHOW VARIABLES和命令行,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • MySQL字符串的拼接、截取、替換、查找位置實例詳解

    MySQL字符串的拼接、截取、替換、查找位置實例詳解

    MySQL中的字符串操作包括拼接、截取、替換和查找位置等功能,本文給大家介紹MySQL字符串的拼接、截取、替換、查找位置示例詳解,感興趣的朋友一起看看吧
    2024-09-09
  • mysql tmp_table_size優(yōu)化之設(shè)置多大合適

    mysql tmp_table_size優(yōu)化之設(shè)置多大合適

    這篇文章主要介紹了mysql tmp_table_size優(yōu)化問題,很多朋友都會問tmp_table_size設(shè)置多大合適,其實既然你都搜索到這篇文章了,一般大于64M比較好,當(dāng)然你也可以可以根據(jù)自己的機(jī)器內(nèi)容配置增加,一般64位的系統(tǒng)能充分利用大內(nèi)存
    2016-05-05
  • insert...on?duplicate?key?update語法詳解

    insert...on?duplicate?key?update語法詳解

    本文主要介紹了insert...on?duplicate?key?update語法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • MySQL數(shù)據(jù)庫命令

    MySQL數(shù)據(jù)庫命令

    這篇文章主要介紹了數(shù)據(jù)庫的常用命令,數(shù)據(jù)庫中對表的命令以及一些常用的數(shù)據(jù)庫查詢和常用函數(shù),感興趣的小伙伴可以借鑒一下
    2023-03-03
  • mysql數(shù)據(jù)庫在表中添加數(shù)據(jù)三種操作方式

    mysql數(shù)據(jù)庫在表中添加數(shù)據(jù)三種操作方式

    這篇文章主要介紹了mysql數(shù)據(jù)庫在表中添加數(shù)據(jù)三種方式,首先創(chuàng)建數(shù)據(jù)庫和表,創(chuàng)建完成后就可以進(jìn)行添加數(shù)據(jù)的操作了,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • MySQL創(chuàng)建并調(diào)用自定義函數(shù)方式

    MySQL創(chuàng)建并調(diào)用自定義函數(shù)方式

    這篇文章主要介紹了MySQL創(chuàng)建并調(diào)用自定義函數(shù)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • mysql登錄報錯提示:ERROR 1045 (28000)的解決方法

    mysql登錄報錯提示:ERROR 1045 (28000)的解決方法

    這篇文章主要介紹了mysql登錄報錯提示:ERROR 1045 (28000)的解決方法,詳細(xì)分析了出現(xiàn)MySQL登陸錯誤的原因與對應(yīng)的解決方法,需要的朋友可以參考下
    2016-04-04
  • MySQL中sum函數(shù)使用的實例教程

    MySQL中sum函數(shù)使用的實例教程

    這篇文章主要給大家介紹了關(guān)于MySQL中sum函數(shù)使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論

泰州市| 特克斯县| 获嘉县| 全州县| 弥渡县| 延边| 泸水县| 徐汇区| 绥中县| 杭锦旗| 治县。| 鹤峰县| 丰都县| 武宁县| 黑河市| 久治县| 板桥市| 浦县| 大连市| 贡觉县| 崇仁县| 广德县| 蛟河市| 广宁县| 大悟县| 茶陵县| 富平县| 盖州市| 南宁市| 古丈县| 宜宾市| 介休市| 长丰县| 仙游县| 萍乡市| 岳阳市| 临澧县| 噶尔县| 永善县| 青海省| 阿拉善左旗|