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

MySQL的幾種分頁(yè)方式,你知道幾種方式

 更新時(shí)間:2023年06月16日 00:11:54   作者:碼農(nóng)桃子  
這篇文章主要介紹了MySQL的幾種分頁(yè)方式,需要的朋友可以參考下

分頁(yè)方式

MySQL目前常用的分頁(yè)方式有兩種:

  • 利用limit實(shí)現(xiàn)分頁(yè),語(yǔ)法為“SELECT*FROM 表名 limit 開(kāi)始記錄數(shù),每頁(yè)條數(shù)”;
  • 利用主鍵索引實(shí)現(xiàn)分頁(yè),語(yǔ)法為“SELECT*FROM 表名 WHERE 字段名 > (頁(yè)數(shù)*10) LIMIT 條數(shù)”

一般使用第一種方式居多,適用于數(shù)據(jù)量不大的場(chǎng)景:

-- 0是開(kāi)始的記錄數(shù),10是條數(shù)SELECT * FROM user LIMIT 0,10;

如果換成第二種寫(xiě)法:

SELECT * FROM user WHERE id > (0*10) LIMIT 10

id是主鍵。如果是第X頁(yè)共Y條:(X從0開(kāi)始計(jì)算)

SELECT * FROM user WHERE id > (X*10) LIMIT Y

當(dāng)然,這種寫(xiě)法存在一定問(wèn)題,如果第0頁(yè)的id=5的數(shù)據(jù)被刪除了,就會(huì)導(dǎo)致查詢(xún)第0頁(yè)的數(shù)據(jù)和第1頁(yè)的數(shù)據(jù)有重合,第0頁(yè)是1-4,6-11(默認(rèn)一頁(yè)10條數(shù)據(jù),因?yàn)閘imit 10,所以會(huì)查詢(xún)到id=11),第二頁(yè)就是11-20,可見(jiàn)id=11重合了。

當(dāng)然關(guān)于id不連續(xù)的問(wèn)題,你可以“邏輯刪除”,增加一個(gè) isdel 的屬性,當(dāng)isdel=1時(shí)表明該數(shù)據(jù)“已經(jīng)刪除”。

但是對(duì)于大量數(shù)據(jù)來(lái)說(shuō),這種問(wèn)題是可以忽視的。

主要的是,這種大量數(shù)據(jù)的表,是機(jī)會(huì)不會(huì)去對(duì)其進(jìn)行刪除甚至修改操作的。

那么為什么大量數(shù)據(jù)使用第二種更合理呢?我們使用MySQL的關(guān)鍵字explain來(lái)看一下大概。

EXPLAIN SELECT * FROM test LIMIT 0,10

其他參數(shù)不做說(shuō)明,就看type:掃描類(lèi)型

效率從最好到最壞依次是:system > const > eqref > ref > fulltext > refornull > indexmerge > uniquesubquery > indexsubquery > range > index > ALL

可見(jiàn)limit的分頁(yè)效果最差。

當(dāng)然,實(shí)際當(dāng)中你可以增加一些查詢(xún)參數(shù),讓查詢(xún)不再走全表掃描。

做對(duì)比的話就不增加查詢(xún)條件了。

EXPLAIN SELECT * FROM test WHERE id > (0*10) LIMIT 10

這個(gè)走的是range  范圍查詢(xún)  明顯好多了。

但這實(shí)際上還是通過(guò)主鍵的查詢(xún),取巧了而已。并且主鍵有主鍵索引,查詢(xún)更快。

一般情況下,得保證查詢(xún)至少達(dá)到range級(jí)別,最好能達(dá)到ref。

第一種方式和第二種方式當(dāng)數(shù)據(jù)量不多的時(shí)候,是第一種方式占優(yōu)勢(shì),畢竟沒(méi)有數(shù)據(jù)重合的問(wèn)題,并且查詢(xún)的速度也沒(méi)有明顯差別。但是當(dāng)數(shù)據(jù)量上去了,差別就很明顯了,

SELECT * FROM test LIMIT 0,10

SELECT * FROM test LIMIT 100,10

查詢(xún)速度是不一樣的 ,查詢(xún)了第100頁(yè)時(shí),實(shí)際上前99頁(yè)都已經(jīng)被掃描過(guò)。

所以第二種的方式更適用于大量數(shù)據(jù)的場(chǎng)景

那么關(guān)于第一種,再多說(shuō)一些。你可以通過(guò)增加一些查詢(xún)參數(shù)去限制type,但是參數(shù)加的不好甚至還不如不加!牽涉到回表問(wèn)題。

關(guān)于回表:

先了解一些B+樹(shù):

 在這個(gè)樹(shù)狀結(jié)構(gòu)里,我們需要關(guān)注的是,最下面一層節(jié)點(diǎn),也就是 葉子結(jié)點(diǎn) 。而這個(gè)葉子結(jié)點(diǎn)里放的信息會(huì)根據(jù)當(dāng)前的索引是 主鍵還是非主鍵 有所不同。

  • 如果是 主鍵索引 ,它的葉子節(jié)點(diǎn)會(huì)存放完整的行數(shù)據(jù)信息。
  • 如果是 非主鍵索引 ,那它的葉子節(jié)點(diǎn)則會(huì)存放主鍵,如果想獲得行數(shù)據(jù)信息,則需要再跑到主鍵索引去拿一次數(shù)據(jù),這叫 回表 。(實(shí)際上查詢(xún)了兩次表)

比如執(zhí)行:

select * from page where user_name = "小白10";

會(huì)通過(guò)非主鍵索引去查詢(xún) user_name 為" 小白10 "的數(shù)據(jù),然后在葉子結(jié)點(diǎn)里找到" 小白10 "的數(shù)據(jù)對(duì)應(yīng)的 主鍵為10 。

此時(shí)回表到 主鍵索引 中做查詢(xún),最后定位到 主鍵為10的行數(shù)據(jù) 。

但不管是主鍵還是非主鍵索引,他們的葉子結(jié)點(diǎn)數(shù)據(jù)都是 有序的 。比如在主鍵索引中,這些數(shù)據(jù)是根據(jù)主鍵id的大小,從小到大,進(jìn)行排序的。

所以說(shuō),如果你加的查詢(xún)參數(shù)是無(wú)索引,是無(wú)序的,那么就是“不如不加”。

那么第一種如何的去優(yōu)化呢? 

上面select后面帶的是 星號(hào) *,也就是要求獲得行

select * from page where id >=(6000000) order by id limit 10;

數(shù)據(jù)的 所有字段信息。

我們結(jié)合第二種可以得到一種優(yōu)化,比如執(zhí)行的是:

select * from page order by id limit 6000000, 10;

由于這次的offset=6000000,會(huì)在innodb里的主鍵索引中獲取到第0到(6000000 + 10)條 完整行數(shù)據(jù), 從引擎層獲取到 很多無(wú)用的數(shù)據(jù) ,而獲取的這些無(wú)用數(shù)據(jù)都是要耗時(shí)的。

當(dāng)select后面是*號(hào)時(shí),就需要拷貝完整的行信息, 拷貝完整數(shù)據(jù) 跟 只拷貝行數(shù)據(jù)里的其中一兩個(gè)列字段 耗時(shí)是不同的,這就讓原本就耗時(shí)的操作變得更加離譜。

因?yàn)榍懊娴膐ffset條數(shù)據(jù)最后都是不要的,就算將完整字段都拷貝來(lái)了又有什么用呢,所以我們可以將sql語(yǔ)句修改成下面這樣:

select * from page where id >=(select id from page order by id limit 6000000, 1) order by id limit 10;

上面這條sql語(yǔ)句,里面先執(zhí)行子查詢(xún) select id from page order by id limit 6000000, 1 , 這個(gè)操作,其實(shí)也是將在innodb中的主鍵索引中獲取到 6000000+1 條數(shù)據(jù),然后server層會(huì)拋棄前6000000條,只保留最后一條數(shù)據(jù)的id。

但不同的地方在于,在返回server層的過(guò)程中,只會(huì)拷貝數(shù)據(jù)行內(nèi)的id這一列,而不會(huì)拷貝數(shù)據(jù)行的所有列,當(dāng)數(shù)據(jù)量較大時(shí),這部分的耗時(shí)還是比較明顯的。

在拿到了上面的id之后,假設(shè)這個(gè)id正好等于6000000,那sql就變成了

select * from page where id >=(6000000) order by id limit 10;

這樣innodb再走一次 主鍵索引 ,通過(guò)B+樹(shù)快速定位到id=6000000的行數(shù)據(jù),時(shí)間復(fù)雜度是lg(n),然后向后取10條數(shù)據(jù)。

這樣性能確實(shí)是提升了,親測(cè)能快一倍左右,屬于那種耗時(shí)從3s變成1.5s的操作。

這······

屬實(shí)有些杯水車(chē)薪,有點(diǎn)搓,屬于沒(méi)辦法中的辦法。

基于非主鍵索引的limit執(zhí)行過(guò)程

上面提到的是主鍵索引的執(zhí)行過(guò)程,我們?cè)賮?lái)看下基于 非主鍵索引 的limit執(zhí)行過(guò)程。

比如下面的sql語(yǔ)句

select * from page order by user_name limit 0, 10;

server層會(huì)調(diào)用innodb的接口,在innodb里的非主鍵索引中獲取到第0條數(shù)據(jù)對(duì)應(yīng)的主鍵id后, 回表 到主鍵索引中找到對(duì)應(yīng)的完整行數(shù)據(jù),然后返回給server層,server層將其放到結(jié)果集中,返回給客戶端。

而當(dāng)offset>0時(shí),且offset的值較小時(shí),邏輯也類(lèi)似,區(qū)別在于,offset>0時(shí)會(huì)丟棄前面的offset條數(shù)據(jù)。

也就是說(shuō)非主鍵索引的limit過(guò)程,比主鍵索引的limit過(guò)程,多了個(gè)回表的消耗。

但當(dāng)offset變得非常大時(shí),比如600萬(wàn),此時(shí)執(zhí)行explain。

非主鍵索引offset值超大時(shí)走全表掃描

可以看到type那一欄顯示的是ALL,也就是 全表掃描 。

這是因?yàn)閟erver層的 優(yōu)化器 ,會(huì)在執(zhí)行器執(zhí)行sql語(yǔ)句前,判斷下哪種執(zhí)行計(jì)劃的代價(jià)更小。

很明顯,優(yōu)化器在看到非主鍵索引的600w次回表之后,搖了搖頭,還不如全表一條條記錄去判斷算了,于是選擇了全表掃描。

因此,當(dāng)limit offset過(guò)大時(shí),非主鍵索引查詢(xún)非常容易變成全表掃描。是真·性能殺手。

這種情況也能通過(guò)一些方式去優(yōu)化。比如

select * from page t1, (select id from page order by user_name limit 6000000, 100) t2 WHERE t1.id = t2.id;select id from page order by user_name limit 6000000, 100

先走innodb層的user_name非主鍵索引取出id,因?yàn)橹荒弥麈Iid, 不需要回表 ,所以這塊性能會(huì)稍微快點(diǎn),在返回server層之后,同樣拋棄前600w條數(shù)據(jù),保留最后的100個(gè)id。然后再用這100個(gè)id去跟t1表做id匹配,此時(shí)走的是主鍵索引,將匹配到的100條行數(shù)據(jù)返回。這樣就繞開(kāi)了之前的600w條數(shù)據(jù)的回表。

當(dāng)然,跟上面的case一樣,還是沒(méi)有解決要白拿600w條數(shù)據(jù)然后拋棄的問(wèn)題,這也是非常挫的優(yōu)化。

像這種,當(dāng)offset變得超大時(shí),比如到了百萬(wàn)千萬(wàn)的量級(jí),問(wèn)題就突然變得嚴(yán)肅了。

這里就產(chǎn)生了個(gè)專(zhuān)門(mén)的術(shù)語(yǔ),叫 深度分頁(yè) 。

總結(jié)

limit offset, size 比 limit size 要慢,且offset的值越大,sql的執(zhí)行速度越慢。

當(dāng)offset過(guò)大,會(huì)引發(fā) 深度分頁(yè) 問(wèn)題,目前不管是mysql還是es都沒(méi)有很好的方法去解決這個(gè)問(wèn)題。只能通過(guò)限制查詢(xún)數(shù)量或分批獲取的方式進(jìn)行規(guī)避。

遇到深度分頁(yè)的問(wèn)題,多思考其原始需求,大部分時(shí)候是不應(yīng)該出現(xiàn)深度分頁(yè)的場(chǎng)景的,必要時(shí)多去影響產(chǎn)品經(jīng)理。

如果數(shù)據(jù)量很少,比如1k的量級(jí),且長(zhǎng)期不太可能有巨大的增長(zhǎng),還是用 limit offset, size 的方案吧,整挺好,能用就行。

相關(guān)文章

  • SQL中Limit的基本與高級(jí)用法詳解

    SQL中Limit的基本與高級(jí)用法詳解

    在SQL中LIMIT是一個(gè)用于限制結(jié)果集返回的行數(shù)的子句,這篇文章主要給大家介紹了關(guān)于SQL中Limit的基本與高級(jí)用法,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用sql具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-04-04
  • Linux安裝MySQL的教程

    Linux安裝MySQL的教程

    這篇文章主要介紹了Linux安裝MySQL的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • MySQL中的if和case語(yǔ)句使用總結(jié)

    MySQL中的if和case語(yǔ)句使用總結(jié)

    這篇文章主要介紹了MySQL中的if和case語(yǔ)句使用總結(jié),本文講解了IF語(yǔ)句作為表達(dá)式和流程控制語(yǔ)句使用實(shí)例,需要的朋友可以參考下
    2015-02-02
  • linux下使用RPM安裝mysql5.7.17

    linux下使用RPM安裝mysql5.7.17

    這篇文章主要為大家詳細(xì)介紹了linux下使用RPM安裝mysql5.7.17的相關(guān)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 深入淺析MySQL從刪庫(kù)到跑路_高級(jí)(一)——數(shù)據(jù)完整性

    深入淺析MySQL從刪庫(kù)到跑路_高級(jí)(一)——數(shù)據(jù)完整性

    數(shù)據(jù)完整性是指數(shù)據(jù)的可靠性和準(zhǔn)確性,數(shù)據(jù)完整性類(lèi)型有四種,本文給大家提到,接下來(lái)通過(guò)本文給大家介紹MySQL從刪庫(kù)到跑路的內(nèi)容分析,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • mysql性能優(yōu)化工具--tuner-primer使用介紹

    mysql性能優(yōu)化工具--tuner-primer使用介紹

    這篇文章主要介紹了mysql性能優(yōu)化工具--tuner-primer的使用方法與返回?cái)?shù)據(jù)分析,需要的朋友可以參考下
    2016-05-05
  • MySQL執(zhí)行計(jì)劃的深入分析

    MySQL執(zhí)行計(jì)劃的深入分析

    這篇文章主要給大家介紹了關(guān)于MySQL執(zhí)行計(jì)劃的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • MySQL數(shù)據(jù)庫(kù)內(nèi)置函數(shù)和內(nèi)外連圖文教程

    MySQL數(shù)據(jù)庫(kù)內(nèi)置函數(shù)和內(nèi)外連圖文教程

    MySQL提供了豐富的內(nèi)置函數(shù),這些函數(shù)使得數(shù)據(jù)的維護(hù)與管理更加方便,能夠更好地提供數(shù)據(jù)的分析與統(tǒng)計(jì)功能,這篇文章主要介紹了MySQL數(shù)據(jù)庫(kù)內(nèi)置函數(shù)和內(nèi)外連的相關(guān)資料,需要的朋友可以參考下
    2026-01-01
  • Mysql數(shù)據(jù)庫(kù) ALTER 操作詳解

    Mysql數(shù)據(jù)庫(kù) ALTER 操作詳解

    這篇文章主要介紹了Mysql數(shù)據(jù)庫(kù) ALTER 操作詳解的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • MySQL正則表達(dá)式匹配查詢(xún)(含實(shí)例)

    MySQL正則表達(dá)式匹配查詢(xún)(含實(shí)例)

    MySQL中正式表達(dá)式通常被用來(lái)檢索或替換符合某個(gè)模式的文本內(nèi)容,根據(jù)指定的匹配模式匹配文中符合要求的特殊字符串,下面這篇文章主要給大家介紹了關(guān)于MySQL正則表達(dá)式匹配查詢(xún)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09

最新評(píng)論

金川县| 板桥市| 银川市| 永寿县| 忻城县| 吴堡县| 潮安县| 葵青区| 威宁| 张家港市| 朝阳区| 凌云县| 福泉市| 什邡市| 云安县| 孙吴县| 抚松县| 会宁县| 新巴尔虎右旗| 平定县| 津南区| 林周县| 铜川市| 大城县| 台南市| 鹤峰县| 金湖县| 湾仔区| 启东市| 错那县| 霸州市| 韶山市| 临汾市| 仁布县| 五寨县| 鹤峰县| 英吉沙县| 策勒县| 牡丹江市| 舞钢市| 吴旗县|