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

淺析MySQL查詢?nèi)ブ厥鞘褂肬NION還是DISTINCT

 更新時間:2026年07月24日 08:33:25   作者:detayun  
本文對比分析了MySQL中去重操作DISTINCT與UNION/UNION ALL的核心差異,文內(nèi)將徹底講透為什么UNION ALL+DISTINCT比UNION更快,以及單表去重、多表合并等不同場景下的最佳選型,幫你避免線上慢查詢和性能故障

前言

開發(fā)過程中經(jīng)常面臨數(shù)據(jù)去重需求,大家常會糾結(jié)兩種方案:

  1. 使用 DISTINCT 在單條結(jié)果集中完成去重;
  2. 使用 UNION 合并多條查詢并自動去重。

還有很多開發(fā)者分不清 UNIONUNION ALL 的巨大差異,經(jīng)常誤用導致數(shù)據(jù)庫出現(xiàn)不必要的性能消耗。

本文對比兩者原理、適用場景、性能差距,給出線上環(huán)境選型標準。

一、先理清基礎(chǔ)語法與核心行為

1. DISTINCT

作用:對單條SQL的結(jié)果集進行去重。

SELECT DISTINCT user_id FROM `user_login_log` WHERE `date` = CURDATE();

執(zhí)行邏輯:數(shù)據(jù)庫取出所有滿足條件的數(shù)據(jù),按照指定字段進行分組對比,剔除重復行,保留唯一記錄。

2. UNION 與 UNION ALL(重點區(qū)分)

-- UNION:合并結(jié)果 + 自動去重 + 排序
SELECT user_id FROM `user` WHERE status = 1
UNION
SELECT user_id FROM `app_key` WHERE status = 1;

-- UNION ALL:僅簡單縱向拼接,**不去重、不排序**
SELECT user_id FROM `user` WHERE status = 1
UNION ALL
SELECT user_id FROM `app_key` WHERE status = 1;

很多人踩坑:以為 UNION = UNION ALL,二者性能差距極大。

UNION = UNION ALL + DISTINCT + 排序操作

二、底層實現(xiàn)原理對比

DISTINCT 原理

在結(jié)果集內(nèi)部構(gòu)建臨時內(nèi)存哈希表或者排序緩沖區(qū),遍歷數(shù)據(jù)消除本行內(nèi)重復記錄。

數(shù)據(jù)量較小使用內(nèi)存;數(shù)據(jù)量大超過緩沖區(qū)限制,則落地磁盤臨時文件,性能斷崖下跌。

UNION 原理

  1. 分別執(zhí)行前后兩條子查詢;
  2. 使用 UNION ALL 把所有數(shù)據(jù)縱向匯總;
  3. 全局執(zhí)行一次DISTINCT排序去重。

簡單公式:

UNION = UNION ALL + DISTINCT

三、核心性能結(jié)論

  1. 如果業(yè)務需要合并多條SQL結(jié)果并且去重:可以使用 UNION
  2. 如果多條SQL合并,原始數(shù)據(jù)不存在重復,優(yōu)先使用 UNION ALL,不要用 UNION;
  3. 如果只是單表/單條查詢內(nèi)部去重,不要使用 UNION,直接使用 DISTINCT
  4. 杜絕濫用 UNION 實現(xiàn)單條SQL內(nèi)部去重,屬于完全錯誤用法。

四、場景分類實戰(zhàn)分析

場景1:單條查詢內(nèi)部去除重復數(shù)據(jù)

? DISTINCT

需求:查詢當日登錄日志里所有活躍用戶ID,同一用戶多條登錄記錄只展示一次。

-- 正確寫法
SELECT DISTINCT user_id FROM user_login_log WHERE `date` = CURDATE();

-- ? 錯誤示范,沒必要強行拆分UNION
SELECT user_id FROM user_login_log WHERE `date` = CURDATE()
UNION
SELECT user_id FROM user_login_log WHERE `date` = CURDATE();

強行使用UNION會執(zhí)行兩次相同查詢,掃描雙倍數(shù)據(jù),額外執(zhí)行全局去重,資源翻倍浪費。

場景2:多條獨立查詢結(jié)果合并,需要全局去重

需求:從用戶表、密鑰表兩處查詢user_id,合并結(jié)果,同一個user_id只保留一條。

方案A UNION

SELECT user_id FROM `user` WHERE username = 'demo'
UNION
SELECT user_id FROM `app_key` WHERE access_key = 'demo_key';

方案B 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;

重點:方案A 和方案B哪個更快?

絕大多數(shù)情況下:UNION ALL + 外層DISTINCT 性能 ≥ UNION

原因:

UNION默認會附帶排序行為;

而外層DISTINCT優(yōu)化器可以選擇哈希去重,不一定強制排序,優(yōu)化空間更大。

追求穩(wěn)定高性能,推薦統(tǒng)一使用 UNION ALL + DISTINCT 寫法,避免UNION隱性排序帶來開銷。

場景3:多條查詢合并,明確不存在重復數(shù)據(jù)

直接使用 UNION ALL,不要使用UNION,不要額外加DISTINCT

省去全局比較、排序、去重的巨大開銷。

SELECT id FROM `user` LIMIT 100
UNION ALL
SELECT id FROM `app_key` LIMIT 100;

五、高頻誤區(qū)匯總

誤區(qū)1:UNION 和 DISTINCT 可以隨意互相替換

不能替換。

DISTINCT作用于單查詢內(nèi)部;

UNION作用于多條查詢合并之后,適用場景邊界完全不同。

誤區(qū)2:UNION去重性能優(yōu)于 UNION ALL + DISTINCT

恰恰相反。

UNION強制執(zhí)行排序去重;UNION ALL只做拼接,把去重選擇權(quán)交給外層,優(yōu)化器擁有更多優(yōu)化策略。

誤區(qū)3:少量數(shù)據(jù),隨便寫無所謂

在測試環(huán)境少量數(shù)據(jù)看不出差距;當結(jié)果集上萬、十萬級別,UNION額外排序會直接引發(fā)慢查詢,線上極易爆出性能故障。

誤區(qū)4:不知道UNION自帶排序,導致不必要的消耗

MySQL UNION規(guī)范:合并完成后會執(zhí)行排序操作;如果你不需要排序,不要使用UNION。

六、索引層面額外優(yōu)化提示

DISTINCT查詢盡量建立覆蓋索引,避免大量回表;

-- 示例:利用索引直接完成去重,無需讀取原始數(shù)據(jù)表
CREATE INDEX idx_date_user ON user_login_log(`date`,user_id);

UNION ALL拆分多條查詢時,每條子查詢務必保證可以正常命中索引;

如果最終只需要獲取第一條匹配記錄,可以每層子查詢增加 LIMIT 實現(xiàn)短路查詢,減少掃描行數(shù)。

七、選型決策清單(線上直接套用)

  1. 單條SQL內(nèi)部去重 → 使用 DISTINCT
  2. 多條SQL結(jié)果合并,存在重復且需要去重 → 優(yōu)先:UNION ALL + 外層DISTINCT
  3. 多條SQL結(jié)果合并,確認無重復 → 使用 UNION ALL
  4. 禁止:單條查詢場景強行拆分使用UNION做去重
  5. 禁止:能用UNION ALL的場景隨意使用UNION

八、驗證手段

使用 EXPLAIN 觀察執(zhí)行計劃:

  • UNION:通常能看到 Using temporary; Using filesort(臨時表+文件排序)
  • UNION ALL:沒有全局排序與臨時表,執(zhí)行計劃更加簡潔

總結(jié)一句話:去重工具沒有絕對好壞,分清場景再選擇;能使用 UNION ALL 就不要使用 UNION,能避免全局排序就盡量避免。

延伸業(yè)務小案例(你項目常用場景)

根據(jù)賬號、郵箱、密鑰多條件檢索用戶ID:

-- 最優(yōu)寫法
SELECT DISTINCT user_id FROM (
    SELECT user_id FROM `user` WHERE username = 'demo'
    UNION ALL
    SELECT user_id FROM `user` WHERE email = 'demo@test.com'
    UNION ALL
    SELECT user_id FROM `app_key` WHERE access_key = 'demo_key'
) tmp;

相比直接寫三條UNION,性能更好,也是線上檢索場景標準寫法。

到此這篇關(guān)于淺析MySQL查詢?nèi)ブ厥鞘褂肬NION還是DISTINCT的文章就介紹到這了,更多相關(guān)MySQL查詢?nèi)ブ貎?nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL連接異常報10061錯誤問題解決

    MySQL連接異常報10061錯誤問題解決

    這篇文章主要介紹了MySQL連接異常報10061錯誤問題解決,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • MySQL5.7.18修改密碼的方法

    MySQL5.7.18修改密碼的方法

    這篇文章主要介紹了MySQL5.7.18修改密碼的方法,非常不錯,具有參考解決價值,需要的朋友可以參考下
    2017-05-05
  • 關(guān)于MySQL繞過授予information_schema中對象時報ERROR 1044(4200)錯誤

    關(guān)于MySQL繞過授予information_schema中對象時報ERROR 1044(4200)錯誤

    這篇文章主要介紹了關(guān)于MySQL繞過授予information_schema中對象時報ERROR 1044(4200)錯誤,本文給大家分享解決方法,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • MySQL啟動失敗報錯:mysqld.service failed to run ‘start-pre‘ task的問題分析與解決方案

    MySQL啟動失敗報錯:mysqld.service failed to run 

    在日常運維中,MySQL 作為廣泛應用的關(guān)系型數(shù)據(jù)庫,其穩(wěn)定性和可用性至關(guān)重要,然而,有時系統(tǒng)升級或配置變更后,MySQL 服務可能會出現(xiàn)無法啟動的問題,本文針對某次實際案例進行深入分析和處理,需要的朋友可以參考下
    2024-12-12
  • MYSQL中information_schema的使用

    MYSQL中information_schema的使用

    information_schema是MySQL中的一個虛擬數(shù)據(jù)庫,用于提供關(guān)于 MySQL 服務器及其數(shù)據(jù)庫的元數(shù),這些元數(shù)據(jù)包括數(shù)據(jù)庫名稱、表名稱、列的數(shù)據(jù)類型、訪問權(quán)限等信息,下面就來詳細的介紹一下如何使用,感興趣的可以了解一下
    2025-08-08
  • mysql創(chuàng)建的外鍵無法保存的原因以及處理辦法

    mysql創(chuàng)建的外鍵無法保存的原因以及處理辦法

    這篇文章主要介紹了mysql創(chuàng)建的外鍵無法保存的原因以及處理辦法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • CentOS6.4上使用yum安裝mysql

    CentOS6.4上使用yum安裝mysql

    這篇文章主要為大家詳細介紹了CentOS6.4上使用yum安裝mysql圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • MySQL業(yè)務數(shù)據(jù)量增長到單表成為瓶頸時的解決方案

    MySQL業(yè)務數(shù)據(jù)量增長到單表成為瓶頸時的解決方案

    文章詳細介紹了MySQL在單表數(shù)據(jù)量增長到瓶頸時的解決方案,包括應急與優(yōu)化、架構(gòu)升級和終極解決方案,本文結(jié)合實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • MySQL中UNION與UNION ALL的基本使用方法

    MySQL中UNION與UNION ALL的基本使用方法

    這篇文章主要給大家介紹了關(guān)于MySQL中UNION與UNION ALL的基本使用方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用MySQL具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-12-12
  • MySQL超詳細實現(xiàn)用戶管理實例

    MySQL超詳細實現(xiàn)用戶管理實例

    MySQL 是一個多用戶數(shù)據(jù)庫,具有功能強大的訪問控制系統(tǒng),可以為不同用戶指定不同權(quán)限。在前面的章節(jié)中我們使用的是 root 用戶,該用戶是超級管理員,擁有所有權(quán)限,包括創(chuàng)建用戶、刪除用戶和修改用戶密碼等管理權(quán)限
    2022-06-06

最新評論

南宫市| 安泽县| 郯城县| 香格里拉县| 古交市| 左权县| 靖宇县| 萍乡市| 沂源县| 扶余县| 福泉市| 饶平县| 武胜县| 六安市| 清河县| 怀远县| 新闻| 定西市| 蓬安县| 四会市| 丰顺县| 浪卡子县| 宜宾县| 开远市| 鹰潭市| 巴里| 马山县| 正安县| 开原市| 隆回县| 昌都县| 九龙坡区| 廊坊市| 邹城市| 宁陕县| 土默特左旗| 剑川县| 古蔺县| 固始县| 会东县| 六安市|