1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        深度分頁(yè),我都是這么玩的

        共 2132字,需瀏覽 5分鐘

         ·

        2022-02-17 20:31

        點(diǎn)擊上方藍(lán)字“設(shè)為星標(biāo)”





        大家好,我是架構(gòu)擺渡人。這是實(shí)踐經(jīng)驗(yàn)系列的第十一篇文章,這個(gè)系列會(huì)給大家分享很多在實(shí)際工作中有用的經(jīng)驗(yàn),如果有收獲,還請(qǐng)分享給更多的朋友。
        ?
        分頁(yè)查詢,無(wú)論是在B端的系統(tǒng),還是C端的應(yīng)用,都有著廣泛的應(yīng)用。只不過(guò)是應(yīng)用方式和對(duì)性能的要求不一樣而已。
        ?
        在B端的系統(tǒng)中一般都是一個(gè)列表,下面有一個(gè)分頁(yè)的組件,可以選擇第幾頁(yè)的數(shù)據(jù),可以進(jìn)行上下分頁(yè),這種就是最常見(jiàn)的分頁(yè)方式,對(duì)應(yīng)到數(shù)據(jù)庫(kù)中我們常實(shí)現(xiàn)的方式就是limit 0,10這種。
        ?
        在C端的應(yīng)用中,也有分頁(yè)查詢的場(chǎng)景,但是對(duì)應(yīng)性能要求比較高,我們都知道傳統(tǒng)limit在頁(yè)數(shù)越大的時(shí)候,性能也越差,主要是跳過(guò)的數(shù)據(jù)越多,回表的次數(shù)也多,這些時(shí)間都浪費(fèi)了。所以一般都不會(huì)在C端應(yīng)用中使用傳統(tǒng)的分頁(yè)方式。
        ?
        其次C端應(yīng)用的分頁(yè)都是沒(méi)有分頁(yè)組件的,以訂單列表來(lái)說(shuō),是個(gè)分頁(yè)查詢的場(chǎng)景,在APP中是滑動(dòng)下拉加載分頁(yè)。
        ?
        為了提高性能,一般會(huì)采用ID直接定位的方式來(lái)做分頁(yè),改寫SQL如下:

        ?

        select * from table where id < #{lastId} order by id desc limit #{limit}

        ?

        改寫之后,就能根據(jù)上次返回的ID直接通過(guò)聚簇索引定位,然后取出對(duì)應(yīng)的條數(shù)即可。
        ?
        這樣改完之后,無(wú)論用戶滑到多少頁(yè),性能都是很快的。但是這種方式也會(huì)存在一個(gè)問(wèn)題,就是你的主鍵ID必須是自增有序才行。可能有同學(xué)會(huì)問(wèn):還有無(wú)序的主鍵ID嗎?
        ?
        肯定是有的,假設(shè)你們業(yè)務(wù)發(fā)展很快,需要考慮整個(gè)機(jī)房不能提供服務(wù)的場(chǎng)景,這個(gè)時(shí)候就需要做異地多活了。
        ?
        在多活場(chǎng)景下,如果是單元庫(kù),會(huì)進(jìn)行雙向復(fù)制,此時(shí)主鍵ID如果都是自增的就會(huì)存在沖突問(wèn)題。當(dāng)然可以通過(guò)設(shè)置不同機(jī)房不同的自增步長(zhǎng)來(lái)解決,這種方式不太靈活,當(dāng)后面擴(kuò)機(jī)房的時(shí)候又需要調(diào)整。
        ?
        另一種方式就是接入分布式ID,分布式ID一般的解決方案有snowflake,segment等。但在分布式場(chǎng)景下要提供完全遞增有序的很難,所以上面的分頁(yè)也會(huì)存在一定的問(wèn)題。比如訂單列表,用戶下完單后去列表查看,很有可能最新的訂單不在第一條,因?yàn)槟愕腎D不是全局遞增。
        ?
        這樣的問(wèn)題我們?nèi)绾谓鉀Q呢?大家想想,在現(xiàn)實(shí)生活中什么是遞增的呢?答案就是時(shí)間。
        ?
        所以,我們可以在表中單獨(dú)加個(gè)時(shí)間字段來(lái)保證有序性。這個(gè)時(shí)間的精度一定要高,比如微妙,納秒級(jí)別,這樣的高精度才能防止重復(fù)。還得建一個(gè)唯一索引來(lái)保證唯一性,確保萬(wàn)無(wú)一失。
        ?
        有了這個(gè)時(shí)間字段,程序就不要去賦值了,直接使用數(shù)據(jù)庫(kù)的默認(rèn)值,當(dāng)然批量插入需要注意,因?yàn)榕坎迦氲臅r(shí)間會(huì)一樣,所以程序中要禁止批量插入。
        ?
        假設(shè)時(shí)間字段有重復(fù)的,會(huì)對(duì)分頁(yè)造成影響嗎?肯定有影響的,我們舉個(gè)例子看下就知道了。

        ?

        4     2022-01-01 12:12:12.1114313     2022-01-01 12:12:12.1114312     2022-01-01 12:12:10.1114311     2022-01-01 12:12:09.111431

        ?

        我們的SQL如下:

        ?

        select * from table order by time desc limit 1

        ?

        那么第一頁(yè)的時(shí)候是沒(méi)有l(wèi)astTime值的,所以在拼接SQL的地方要做判斷。第一頁(yè)查出的數(shù)據(jù)是ID為1,時(shí)間為2022-01-01 12:12:12.111431的數(shù)據(jù)。
        ?
        第二頁(yè)的SQL如下:
        select * from table where time < '2022-01-01 12:12:12.111431' order by time desc limit 1

        ?

        獲取的結(jié)果是ID為3,時(shí)間為2022-01-01 12:12:10.111431的數(shù)據(jù),你會(huì)發(fā)現(xiàn)ID為2的數(shù)據(jù)丟失了,因?yàn)樗臅r(shí)間跟第一條一模一樣,這就是問(wèn)題所在,所以我們要保證時(shí)間字段的唯一性。
        ?
        如果非得要通過(guò)SQL解決也是可以的,我們可以將查詢的SQL改寫下,如下:

        ?

        select * from table where time < '2022-01-01 12:12:12.111431' or (time='2022-01-01 12:12:12.111431' and id < 4) order by time desc,id desc limit 1

        ?

        通過(guò)加入or條件匹配最后一個(gè)時(shí)間,如果時(shí)間又相同的就會(huì)符合條件,并且這條數(shù)據(jù)的時(shí)間是小于之前最后一條數(shù)據(jù)的ID, 這樣就可以把重復(fù)的數(shù)據(jù)查出來(lái)了。
        ?
        需要注意的是之前我們返回給客戶端只需要最后一條數(shù)據(jù)的ID, 那么現(xiàn)在就要返回ID+時(shí)間了。

        ?

        大家好,我是從古代穿越過(guò)來(lái)的美男子:架構(gòu)擺渡人。我將把我的武功秘籍全部傳授與你們,覺(jué)得有用請(qǐng)分享給身邊的朋友。來(lái)個(gè)三連吧,感謝各位!另外我還在B站錄制《真實(shí)訂單業(yè)務(wù),億級(jí)數(shù)據(jù)帶你實(shí)戰(zhàn)分庫(kù)分表》的實(shí)戰(zhàn)課程,記得去學(xué)習(xí)哦!

        瀏覽 50
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产v日韩 | 国产天堂av电影 国产又黄又爽又色的免费视频 | 成人尻逼视频 | 欧美一级电影在线 | 精品无码人妻一区二区三区影片 | 抽插中文字幕 | 日韩一级片在线视频 | 影音先锋AV色情资源网 | 成人无码www免费视频在线看 | 性爱婷婷 |