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

Mysql排序的特性詳情

 更新時(shí)間:2022年05月25日 14:18:57   作者:程序新視界  
這篇文章主要介紹Mysql排序的特性,新寫了一個(gè)功能,自測(cè)和測(cè)試環(huán)境測(cè)試都沒問題,但在生產(chǎn)環(huán)境會(huì)出現(xiàn)偶發(fā)問題。于是,加班到12點(diǎn)一直排查問題,終于定位了的問題原因:Mysql Limit查詢優(yōu)化導(dǎo)致?,F(xiàn)抽象出問題模型及解決方案,分析給大家,避免大家踩坑,需要的朋友可以參考一下

1、問題場(chǎng)景

新上線一個(gè)交易記錄導(dǎo)出功能,邏輯很簡(jiǎn)單:根據(jù)查詢條件,導(dǎo)出對(duì)應(yīng)的數(shù)據(jù)。由于數(shù)據(jù)量比較大,在查詢數(shù)據(jù)庫(kù)時(shí)采用了分頁(yè)查詢,每次查詢1000條數(shù)據(jù)。

自測(cè)正常,測(cè)試環(huán)境正常,上線之后運(yùn)營(yíng)反饋導(dǎo)出的數(shù)據(jù)有重復(fù)記錄。

原本是以為業(yè)務(wù)邏輯問題,重新Review了一遍代碼,依舊未找到問題原因。最后只好把SQL語(yǔ)句拿出來(lái)單獨(dú)執(zhí)行,導(dǎo)出數(shù)據(jù),對(duì)比發(fā)現(xiàn)竟然是SQL語(yǔ)句查詢結(jié)果亂序?qū)е碌摹?/p>

2、原因分析

查詢語(yǔ)句以create_time進(jìn)行倒序排序,通過(guò)limit進(jìn)行分頁(yè),在正常情況下不會(huì)出現(xiàn)問題。但當(dāng)業(yè)務(wù)并發(fā)量比較大,導(dǎo)致create_time存在大量相同值時(shí),再基于limit進(jìn)行分頁(yè),就會(huì)出現(xiàn)亂序問題。

出現(xiàn)的場(chǎng)景是:create_time排序,當(dāng)create_time存在相同值,通過(guò)limit分頁(yè),導(dǎo)致分頁(yè)數(shù)據(jù)亂序。

比如,查詢1000條數(shù)據(jù),其中有一批create_time記錄值都為”2021-10-28 12:12:12“,當(dāng)創(chuàng)建時(shí)間相同的這些數(shù)據(jù),一部分出現(xiàn)在第一頁(yè),一部分出現(xiàn)在第二頁(yè),在查詢第二頁(yè)的數(shù)據(jù)時(shí),可能會(huì)出現(xiàn)第一頁(yè)已經(jīng)查過(guò)的數(shù)據(jù)。

也就是說(shuō),數(shù)據(jù)會(huì)來(lái)回跳動(dòng),一會(huì)兒出現(xiàn)在第一頁(yè),一會(huì)兒出現(xiàn)在第二頁(yè),這就導(dǎo)致導(dǎo)出的數(shù)據(jù)一部分重復(fù),一部分缺失。

查看了Mysql 5.7和8.0的官方文檔,描述如下:

If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.

上述內(nèi)容概述:在使用ORDER BY對(duì)列進(jìn)行排序時(shí),如果對(duì)應(yīng)(ORDER BY的列)列存在多行相同數(shù)據(jù),(Mysql)服務(wù)器會(huì)按照任意順序返回這些行,并且可能會(huì)根據(jù)整體執(zhí)行計(jì)劃以不同的方式返回。

簡(jiǎn)單來(lái)說(shuō)就是:ORDER BY查詢的數(shù)據(jù),如果ORDER BY列存在多行相同數(shù)據(jù),Mysql會(huì)隨機(jī)返回。這就會(huì)導(dǎo)致雖然使用了排序,但也會(huì)發(fā)生亂序的狀況。

3、解決方案

針對(duì)上述問題,基本的解決思路是:避免ORDER BY列的值出現(xiàn)重復(fù)。因此,可以加入其他維度,比如ID等其他排序列。

select * from tb_order order by create_time ,id desc;

這樣,在create_time相同時(shí),會(huì)根據(jù)id進(jìn)行排序,而id肯定是不同的,就再不會(huì)出現(xiàn)上述問題了。

4、拓展知識(shí)

其實(shí),上述內(nèi)容在Mysql的官網(wǎng)已經(jīng)有明確說(shuō)明,而且還舉了例子。下面對(duì)官網(wǎng)的內(nèi)容和例子做一個(gè)簡(jiǎn)單的匯總總結(jié)。

4.1 limit查詢優(yōu)化

如果我們只是查詢一個(gè)結(jié)果集的一部分,那么不要查詢所有數(shù)據(jù),然后再丟棄不需要的數(shù)據(jù),而是要通過(guò)limit條件來(lái)進(jìn)行限制。

在沒使用having條件時(shí),Mysql可能會(huì)對(duì)limit條件優(yōu)化:

  • 如果只查詢幾條數(shù)據(jù),建議使用limit,這樣Mysql可能會(huì)用到索引,而通常情況下Mysql是全表掃描;
  • 如果將limit row_countorder by結(jié)合使用,Mysql會(huì)在找到第一個(gè)row_count結(jié)果集后立刻停止排序,而不是對(duì)整個(gè)結(jié)果集進(jìn)行排序。如果此時(shí)基于索引進(jìn)行操作,速度會(huì)更快。如果必須進(jìn)行文件排序,在找到row_count結(jié)果集之前,會(huì)對(duì)部分或所有符合條件的結(jié)果進(jìn)行排序。但當(dāng)找到row_count結(jié)果之后,便不會(huì)對(duì)剩余部分進(jìn)行排序了。這種特性的一個(gè)表現(xiàn)就是我們前面提到的帶有l(wèi)imit和不帶limit進(jìn)行查詢時(shí),返回的結(jié)果順序可能不同。
  • 如果將limit row_count和distinct結(jié)合使用,Mysql會(huì)在找到row_count結(jié)果集唯一行后立馬停止。
  • 在某些情況下,可以通過(guò)按照順序讀取索引(或?qū)λ饕M(jìn)行排序),然后計(jì)算摘要直到索引變化來(lái)實(shí)現(xiàn)group by。在這種情況下,limit row_count不會(huì)計(jì)算任何不必要的group by值。
  • 一旦MySQL向客戶端發(fā)送了所需數(shù)量的行,就會(huì)中止查詢,除非使用了SQL_CALC_FOUND_ROWS。在這種情況下,可以使用 SELECT FOUND_ROWS() 檢索行數(shù)。
  • LIMIT 0會(huì)快速返回一個(gè)空集合,通??捎糜跈z查SQL的有效性。還可以用于在應(yīng)用程序中獲得結(jié)果集的類型。在Mysql客戶端中,可以使用--column-type-info來(lái)顯示結(jié)果列類型。
  • 如果使用臨時(shí)表來(lái)解析查詢,Mysql會(huì)使用 limit row_count來(lái)計(jì)算需要多少空間。
  • 如果order by未使用索引,且存在limit條件,則優(yōu)化器可能會(huì)避免使用合并文件,而采用內(nèi)存filesort操作對(duì)內(nèi)存中的行進(jìn)行排序。

了解了limit的一些特性,下面再回到本文的重點(diǎn),limit row_countorder by結(jié)合使用特性。

4.2 limit與order by結(jié)合使用

在上面第二條中已經(jīng)提到,limit row_countorder by結(jié)合呈現(xiàn)的特性之一就是結(jié)果返回的順序是不確定的。而影響執(zhí)行計(jì)劃的一個(gè)因素就是limit,因此帶有limit與不帶有limit執(zhí)行同樣的查詢語(yǔ)句,返回結(jié)果的順序可能不同。

下面示例中,根據(jù)category列進(jìn)行排序查詢,而id和rating是不確定的:

mysql> SELECT * FROM ratings ORDER BY category;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  3 |        2 |    3.7 |
|  4 |        2 |    3.5 |
|  6 |        2 |    3.5 |
|  2 |        3 |    5.0 |
|  7 |        3 |    2.7 |
+----+----------+--------+

當(dāng)查詢語(yǔ)句包含limit時(shí),可能會(huì)影響到category值相同的數(shù)據(jù):

mysql> SELECT * FROM ratings ORDER BY category LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  4 |        2 |    3.5 |
|  3 |        2 |    3.7 |
|  6 |        2 |    3.5 |
+----+----------+--------+

其中id為3和4的結(jié)果位置發(fā)生了變化。

在實(shí)踐中,保持查詢結(jié)果的順序性往往非常重要,此時(shí)就需要引入其他列來(lái)保證結(jié)果的順序性了。

當(dāng)上述實(shí)例引入id之后,查詢語(yǔ)句及結(jié)果如下:

mysql> SELECT * FROM ratings ORDER BY category, id;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  3 |        2 |    3.7 |
|  4 |        2 |    3.5 |
|  6 |        2 |    3.5 |
|  2 |        3 |    5.0 |
|  7 |        3 |    2.7 |
+----+----------+--------+
?
mysql> SELECT * FROM ratings ORDER BY category, id LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  3 |        2 |    3.7 |
|  4 |        2 |    3.5 |
|  6 |        2 |    3.5 |
+----+----------+--------+

可以看出,當(dāng)添加了id列的排序,即使category相同,也不會(huì)出現(xiàn)亂序問題。這正與我們最初的解決方案一致。

5、小結(jié)

本來(lái)通過(guò)實(shí)踐中偶發(fā)的一個(gè)坑,聊到了Mysql對(duì)limit查詢語(yǔ)句的優(yōu)化,同時(shí)提供了解決方案,即滿足了業(yè)務(wù)需求,又避免了業(yè)務(wù)邏輯的錯(cuò)誤。

很多朋友都在使用order bylimit語(yǔ)句進(jìn)行查詢,但如果不知道Mysql的這些優(yōu)化特性,很可能已經(jīng)入坑,只不過(guò)數(shù)據(jù)量沒有觸發(fā)呈現(xiàn)而已。

到此這篇關(guān)于Mysql排序的特性詳情的文章就介紹到這了,更多相關(guān)Mysql排序特性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Mysql中文亂碼問題該如何解決(亂碼問題完美解決方案)

    關(guān)于Mysql中文亂碼問題該如何解決(亂碼問題完美解決方案)

    這篇文章給大家介紹關(guān)于Mysql中文亂碼問題該如何解決(亂碼問題完美解決方案)的相關(guān)資料,還給大家收集些關(guān)于MySQL會(huì)出現(xiàn)中文亂碼原因常見的幾點(diǎn),小伙伴快來(lái)看看吧
    2015-11-11
  • MySQL基礎(chǔ)教程之DML語(yǔ)句詳解

    MySQL基礎(chǔ)教程之DML語(yǔ)句詳解

    DML 語(yǔ)句是指對(duì)數(shù)據(jù)庫(kù)中表的記錄進(jìn)行的操作,下面這篇文章主要給大家介紹了關(guān)于MySQL基礎(chǔ)教程之DML語(yǔ)句的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12
  • MySQL使用UUID_SHORT()的問題解決

    MySQL使用UUID_SHORT()的問題解決

    MySQL的UUID_SHORT()函數(shù)是一個(gè)用于生成短UUID的函數(shù),該函數(shù)返回一個(gè)64位的整數(shù),可以用于唯一標(biāo)識(shí)一條數(shù)據(jù)記錄,本文介紹了MySQL使用UUID_SHORT()的問題解決,感興趣的可以了解一下
    2023-08-08
  • MYsql庫(kù)與表的管理及視圖介紹

    MYsql庫(kù)與表的管理及視圖介紹

    這篇文章主要介紹了MYsql庫(kù)與表的管理及視圖介紹,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • Mybatis的where標(biāo)簽使用總結(jié)梳理

    Mybatis的where標(biāo)簽使用總結(jié)梳理

    這篇文章主要介紹了Mybatis的where標(biāo)簽使用總結(jié)梳理,文章通過(guò)將Mybatis中where標(biāo)簽的基本使用形式展開where標(biāo)簽小技巧以及容易踩到的坑進(jìn)行總結(jié)梳理,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • The MySQL server is running with the --read-only option so it cannot execute this statement

    The MySQL server is running with the --read-only option so i

    1209 - The MySQL server is running with the --read-only option so it cannot execute this statement
    2020-08-08
  • mysql中EXISTS和IN的使用方法比較

    mysql中EXISTS和IN的使用方法比較

    這篇文章主要給大家介紹了關(guān)于mysql中EXISTS和IN使用方法比較的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 解析MSSQL跨數(shù)據(jù)庫(kù)查詢的實(shí)現(xiàn)方法

    解析MSSQL跨數(shù)據(jù)庫(kù)查詢的實(shí)現(xiàn)方法

    本篇文章是對(duì)MSSQL跨數(shù)據(jù)庫(kù)查詢的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • MySQL里的反斜杠(\\)的使用

    MySQL里的反斜杠(\\)的使用

    本文主要介紹了MySQL里的反斜杠(\\)的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • ubuntu16.04.1下 mysql安裝和卸載圖文教程

    ubuntu16.04.1下 mysql安裝和卸載圖文教程

    這篇文章主要介紹了ubuntu16.04.1下 mysql安裝和卸載圖文教程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11

最新評(píng)論

襄垣县| 千阳县| 博野县| 绵阳市| 四子王旗| 罗甸县| 金山区| 余江县| 封丘县| 汕头市| 绥江县| 五家渠市| 石棉县| 惠水县| 确山县| 大余县| 蕉岭县| 登封市| 吉安市| 辽源市| 青铜峡市| 班戈县| 凌云县| 潮州市| 岳西县| 元朗区| 浏阳市| 桦南县| 宜川县| 醴陵市| 雷波县| 清原| 天峨县| 康保县| 肇东市| 宁津县| 禄丰县| 牙克石市| 宜丰县| 三台县| 荣成市|