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

加了?limit?1?查詢竟然變慢了的原因分析及解決辦法

 更新時(shí)間:2026年04月09日 10:05:26   作者:神奇小湯圓  
在使用MySQL進(jìn)行查詢優(yōu)化時(shí),LIMIT語句雖然看似簡單,但如果不注意使用場景,可能會(huì)對(duì)性能造成顯著影響,這篇文章主要介紹了加了limit?1查詢竟然變慢了的原因分析及解決辦法的相關(guān)資料,需要的朋友可以參考下

寫 SQL 的時(shí)候,大家都有個(gè)肌肉記憶:如果只需要一條數(shù)據(jù),一定要加上 LIMIT 1。

這聽起來非常合理,畢竟數(shù)據(jù)庫只要找到一條滿足條件的記錄,就可以收工回家,不用再把剩下的幾百萬行數(shù)據(jù)掃一遍,既省 IO 又省 CPU。

但前兩天排查線上問題時(shí),我遇到了一個(gè)非常有意思的案例:加了 LIMIT 1,查詢反而慢了 50 倍。

這就好比你為了抄近道走了一條小路,結(jié)果發(fā)現(xiàn)這條路堵得水泄不通,比走大路還慢。

1. 還原一下現(xiàn)場

業(yè)務(wù)場景很簡單:我們要查某個(gè)用戶最近的一筆“處理中”的訂單。

訂單表 orders 大概有 500 萬數(shù)據(jù),表里有兩個(gè)關(guān)鍵索引:

  1. idx_user_status(user_id, status):用來根據(jù)用戶和狀態(tài)過濾數(shù)據(jù)。
  2. idx_create_time(create_time):用來按時(shí)間排序。

代碼里的 SQL 是這么寫的:

SELECT id, order_no, amount 
FROM orders 
WHERE user_id = 10086 AND status = 1 
ORDER BY create_time DESC 
LIMIT 1;

這條 SQL 上線后,直接觸發(fā)了慢查詢報(bào)警,耗時(shí)飆到了 2.5 秒。

為了搞清楚原因,我試著把 LIMIT 1 去掉,裸跑了一次:

SELECT id, order_no, amount 
FROM orders 
WHERE user_id = 10086 AND status = 1 
ORDER BY create_time DESC;

結(jié)果只要 50 毫秒。

加了 LIMIT 也就是想省點(diǎn)事,反而變慢了呢?

2. Explain 分析

遇到這種詭異的事,第一反應(yīng)肯定是看執(zhí)行計(jì)劃。對(duì)比了一下兩條 SQL 的 EXPLAIN 結(jié)果,真相立刻浮出水面:

  • 沒加 LIMIT時(shí):   MySQL 選擇了 idx_user_status 索引。它先精準(zhǔn)地把這個(gè)用戶狀態(tài)為 1 的訂單找出來(只有幾十條),然后在內(nèi)存里排個(gè)序。因?yàn)閿?shù)據(jù)量少,這個(gè)排序幾乎瞬間完成。
  • 加了 LIMIT 后:  MySQL 居然放棄了精準(zhǔn)過濾,改用了 idx_create_time 索引。 它的思路變成了,按時(shí)間倒序掃描全表,一邊掃一邊檢查這是不是該用戶的訂單。

為什么優(yōu)化器會(huì)覺得第二種方案更好?

這里我們得站在 MySQL 優(yōu)化器的角度想一想。它在做決策時(shí),其實(shí)是在做一道算術(shù)題:

  • 方案 A 走過濾索引:先把符合條件的數(shù)據(jù)全找出來,再排序。 缺點(diǎn):如果符合條件的數(shù)據(jù)很多,排序成本會(huì)很高。
  • 方案 B 走時(shí)間索引 + LIMIT:既然你只要 1 條數(shù)據(jù),而且要求按時(shí)間倒序,那我就順著時(shí)間索引往回找。優(yōu)點(diǎn):天然有序,不用再排序了。

優(yōu)化器其實(shí)在賭,優(yōu)化器覺得,運(yùn)氣只要不是太差,應(yīng)該很快就能碰到一條滿足 user_id 和 status 的記錄。

問題就出在這個(gè)賭注上。

在這個(gè)案例里,用戶 10086 是個(gè)老用戶,他最近的一筆“處理中”的訂單,其實(shí)是一年前下的。

于是,MySQL 順著時(shí)間索引,從今天的數(shù)據(jù)開始往回掃,掃了昨天、上周、上個(gè)月……一直掃了 200 多萬行數(shù)據(jù),才終于在去年的數(shù)據(jù)里找到了那條記錄。

這就是為什么加了 LIMIT 1 反而變成了全表掃描級(jí)別的慢查詢。

3. 怎么解決?

既然知道了是優(yōu)化器選錯(cuò)路了,那我們的思路就是幫它糾正過來。

方法一:簡單粗暴 FORCE INDEX

既然優(yōu)化器甚至不清楚,那我們就直接教它做事。

SELECT ... FROM orders FORCE INDEX (idx_user_status) ...

這就相當(dāng)于在導(dǎo)航里強(qiáng)制選定路線。優(yōu)點(diǎn)是立竿見影,缺點(diǎn)是代碼不夠優(yōu)雅,如果以后索引名改了,這行代碼會(huì)報(bào)錯(cuò)。

方法二:最穩(wěn)妥的聯(lián)合索引**

優(yōu)化器之所以糾結(jié),是因?yàn)楝F(xiàn)有的索引沒法同時(shí)滿足“過濾”和“排序”。

我們可以建一個(gè)聯(lián)合索引:(user_id, status, create_time)。

在這個(gè)索引里,數(shù)據(jù)先按用戶和狀態(tài)聚在一起,內(nèi)部再按時(shí)間排序。MySQL 只要用這個(gè)索引,既能精準(zhǔn)定位,又不用額外排序,這才是最完美的解法。

方法三:子查詢的小技巧

如果你不想改表結(jié)構(gòu),還有一個(gè)巧妙的寫法:

SELECT * FROM (
    SELECT ... FROM orders 
    WHERE user_id = 10086 AND status = 1 
    ORDER BY create_time DESC
) AS tmp 
LIMIT 1;

我們用一個(gè)子查詢先把數(shù)據(jù)找出來,這時(shí)候 MySQL 會(huì)乖乖走過濾索引,然后再在外層取 LIMIT 1。這就相當(dāng)于人為地切斷了 LIMIT 對(duì)內(nèi)層索引選擇的干擾。

寫在最后

LIMIT 1 確實(shí)是個(gè)好習(xí)慣,但也要看場景。

在這個(gè)案例里,MySQL 的優(yōu)化器因?yàn)檫^度自信,覺得“很快就能找到這一條”,結(jié)果在數(shù)據(jù)分布不均勻的情況下翻了車。

下次如果再遇到加了限制反而變慢的問題,直接用 EXPLAIN 看看,因?yàn)閮?yōu)化器有時(shí)候也是會(huì)做出抽風(fēng)的事!

到此這篇關(guān)于加了limit 1查詢竟然變慢了的原因分析及解決辦法的文章就介紹到這了,更多相關(guān)limit1查詢變慢解決內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL占用CPU過高排查過程及可能優(yōu)化方案

    MySQL占用CPU過高排查過程及可能優(yōu)化方案

    這篇文章主要介紹了MySQL占用CPU過高排查過程及可能優(yōu)化方案,具有很好的參考價(jià)值,希望對(duì)大家的學(xué)習(xí)或工作有所幫助,感興趣的朋友可以參考下
    2024-01-01
  • 關(guān)于Mysql搭建主從復(fù)制功能的步驟實(shí)現(xiàn)

    關(guān)于Mysql搭建主從復(fù)制功能的步驟實(shí)現(xiàn)

    這篇文章主要介紹了關(guān)于Mysql搭建主從復(fù)制功能的步驟實(shí)現(xiàn),在實(shí)際的生產(chǎn)中,為了解決Mysql的單點(diǎn)故障已經(jīng)提高M(jìn)ySQL的整體服務(wù)性能,一般都會(huì)采用主從復(fù)制,需要的朋友可以參考下
    2023-05-05
  • MySQL8.0與MySQL5.7的區(qū)別詳解

    MySQL8.0與MySQL5.7的區(qū)別詳解

    MySQL8.0是2018年4月20日發(fā)布的全球最受歡迎的開源數(shù)據(jù)庫的一個(gè)非常令人興奮的新版本,下面這篇文章主要給大家介紹了關(guān)于MySQL8.0與MySQL5.7區(qū)別的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • mysql中union和union?all的使用及注意事項(xiàng)

    mysql中union和union?all的使用及注意事項(xiàng)

    這篇文章主要給大家介紹了關(guān)于mysql中union和union?all的使用及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • windows10下mysql 8.0 下載與安裝配置圖文教程

    windows10下mysql 8.0 下載與安裝配置圖文教程

    這篇文章主要介紹了windows10下mysql 8.0 下載與安裝配置圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • SQL Server 完整備份遇到的一個(gè)不常見的錯(cuò)誤及解決方法

    SQL Server 完整備份遇到的一個(gè)不常見的錯(cuò)誤及解決方法

    這篇文章給大家介紹了SQL Server 完整備份遇到的一個(gè)不常見的錯(cuò)誤及解決方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2019-05-05
  • mysql 8.0.25 解壓版安裝配置方法圖文教程

    mysql 8.0.25 解壓版安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.25 解壓版安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • mysql下float類型使用一些誤差詳解

    mysql下float類型使用一些誤差詳解

    我想很多朋友都不怎么會(huì)在mysql中使用float類型,特別是用到金錢時(shí)我們可能會(huì)用雙精度來做,我們知道m(xù)ysql的float類型是單精度浮點(diǎn)類型不小心就會(huì)導(dǎo)致數(shù)據(jù)誤差
    2012-11-11
  • Rsyslog + MySQL 實(shí)現(xiàn)日志集中存儲(chǔ)及常見問題排查

    Rsyslog + MySQL 實(shí)現(xiàn)日志集中存儲(chǔ)及常見問題排查

    文章介紹了如何使用rsyslog和MySQL實(shí)現(xiàn)Linux系統(tǒng)日志的集中存儲(chǔ)和統(tǒng)一查詢,它詳細(xì)描述了環(huán)境前置要求、MySQL端配置、rsyslog核心配置、服務(wù)重啟與驗(yàn)證、高級(jí)配置以及常見問題排查,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • mysql導(dǎo)出導(dǎo)入中文表解決方法

    mysql導(dǎo)出導(dǎo)入中文表解決方法

    在開發(fā)過程中會(huì)經(jīng)常用到mysql導(dǎo)出導(dǎo)入中文表,本文將詳細(xì)介紹其如何使用,需要的朋友可以參考下
    2012-11-11

最新評(píng)論

紫金县| 云阳县| 武强县| 南通市| 朝阳县| 勐海县| 金堂县| 灵寿县| 吉木萨尔县| 积石山| 麻城市| 枣强县| 凌云县| 武邑县| 株洲市| 云霄县| 泉州市| 黄平县| 夏邑县| 抚顺市| 广丰县| 镇平县| 禄丰县| 金秀| 英德市| 七台河市| 天镇县| 尤溪县| 平阴县| 武义县| 瓮安县| 哈密市| 准格尔旗| 南宫市| 黄山市| 昆山市| 钦州市| 汉源县| 安丘市| 宜春市| 万荣县|