国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

千萬級數(shù)據(jù)深分頁查詢SQL性能優(yōu)化實(shí)踐

這篇具有很好參考價值的文章主要介紹了千萬級數(shù)據(jù)深分頁查詢SQL性能優(yōu)化實(shí)踐。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

一、系統(tǒng)介紹和問題描述

如何在Mysql中實(shí)現(xiàn)上億數(shù)據(jù)的遍歷查詢?先來介紹一下系統(tǒng)主角:關(guān)注系統(tǒng),主要是維護(hù)京東用戶和業(yè)務(wù)對象之前的關(guān)注關(guān)系;并對外提供各種關(guān)系查詢,比如查詢用戶的關(guān)注商品或店鋪列表,查詢用戶是否關(guān)注了某個商品或店鋪等。但是最近接到了一個新需求,要求提供查詢關(guān)注對象的粉絲列表接口功能。該功能的難點(diǎn)就是關(guān)注對象的粉絲數(shù)量過多,不少店鋪的粉絲數(shù)量都是千萬級別,并且有些大V粉絲數(shù)量能夠達(dá)到上億級別。而這些粉絲列表數(shù)據(jù)目前全都存儲在Mysql庫中,然后通過業(yè)務(wù)對象ID進(jìn)行分庫分表,所有的粉絲列表數(shù)據(jù)分布在16個分片的256張表中。同時為了方便查詢粉絲列表,同一個業(yè)務(wù)對象的所有粉絲都會路由到同一張表中,每個表的數(shù)據(jù)量都能夠達(dá)到 2 億+。

二、解決問題的思路和方法

數(shù)據(jù)庫表結(jié)構(gòu)示例如下:

CREATE TABLE follow_fans_[0-255]
  (
    id bigint(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
    biz_content   VARCHAR(50) DEFAULT NULL COMMENT '業(yè)務(wù)對象ID',
    source        VARCHAR(50) DEFAULT NULL COMMENT '來源',
    pin           VARCHAR(50) DEFAULT NULL COMMENT '用戶pin',
    ext           VARCHAR(5000) DEFAULT NULL COMMENT '擴(kuò)展信息',
    status        TINYINT(2) DEFAULT 1 COMMENT '狀態(tài),0是失效,1是正常',
    created_time  DATETIME DEFAULT NULL COMMENT '創(chuàng)建時間',
    modified_time DATETIME DEFAULT NULL COMMENT '修改時間',
    PRIMARY KEY(id),
    UNIQUE INDEX uniq_biz_content_pin (biz_content, pin)
  )
  ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT = '關(guān)注粉絲表';


Limit實(shí)現(xiàn)

由于同一個業(yè)務(wù)對象的所有粉絲都保存到一張數(shù)據(jù)庫表中,對于分頁查詢列表接口,首先想到的就是用limit實(shí)現(xiàn),對于粉絲數(shù)量很少的關(guān)注對象,查詢接口性能還不錯。但是隨著關(guān)注對象的粉絲數(shù)量越來越多,接口查詢性能就會越來越慢。后來經(jīng)過接口壓測,當(dāng)業(yè)務(wù)對象粉絲列表數(shù)量達(dá)到幾十萬級別的時候,查詢頁碼數(shù)量越大,查詢耗時越多。limit深分頁為什么會變慢?這就和sql的執(zhí)行計劃有關(guān)了,limit語句會先掃描offset+n行,然后再丟棄掉前offset行,返回后n行數(shù)據(jù)。也就是說limit 100000,10,就會掃描100010行,而limit 0,10,只掃描10行。查詢 sql 示例如下:

select  id,biz_content,pin FROM follow_fans_1 where biz_content = #{bizContent} order by id desc limit 10, 10;


  • 方案優(yōu)點(diǎn):實(shí)現(xiàn)簡單,支持跳頁查詢。
  • 方案缺點(diǎn):數(shù)據(jù)量變大時,隨著查詢頁碼的深入,查詢性能越來越差。

標(biāo)簽記錄法

Limit深分頁問題的本質(zhì)原因就是:偏移量(offset)越大,mysql就會掃描越多的行,然后再拋棄掉,這樣就導(dǎo)致查詢性能的下降。所以我們可以采用標(biāo)簽記錄法,就是標(biāo)記一下上次查詢到哪一條了,下次再來查的時候,從該條開始往下掃描。具體做法方式是,查詢粉絲列表中按照自增主鍵ID倒序查詢,查詢結(jié)果中返回主鍵ID,然后查詢?nèi)雲(yún)⒅性黾觤axId參數(shù),該參數(shù)需要透傳上一次請求粉絲列表中最后一條記錄主鍵ID,第一次查詢時可以為空,但是需要查詢下一頁時就必傳。最后根據(jù)查詢時返回的行數(shù)是否等于 10 來判斷整個查詢是否可以結(jié)束。優(yōu)化后的查詢sql參考如下:

select id,biz_content,pin FROM follow_fans_1 where biz_content = #{bizContent} and id < #{lastId} order by id desc limit 10;


  • 方案優(yōu)點(diǎn):避免了數(shù)據(jù)量變大時,頁碼查詢深入的性能下降問題;經(jīng)過接口壓測,千萬級數(shù)據(jù)量時,前 N-1頁查詢耗時可以控制在幾十毫秒內(nèi)。
  • 方案缺點(diǎn):只能支持按照頁碼順序查詢,不支持跳頁,而且僅能保證前 N-1 頁的查詢性能;如果最后一頁的表中行數(shù)量不滿 10 條時,引擎不知道何時終止查詢,只能遍歷全表,所以當(dāng)表中數(shù)據(jù)量很大時,還是會出現(xiàn)超時情況。

區(qū)間限制法

標(biāo)簽記錄法最后一頁查詢超時就是因?yàn)椴恢篮螘r終止查詢,所以我們可以提供一個區(qū)間限制范圍來告訴引擎查詢到此結(jié)束。

查詢sql再次優(yōu)化后參考如下:

select id,biz_content,pin FROM follow_fans_1 where biz_content = #{bizContent} and id < #{lastId} and id >={minId} order by id desc limit 10;


由于查詢時需要帶上 minId 參數(shù),所以在執(zhí)行查詢粉絲列表之前,我們就需要先把 minId 查詢出來,查詢 sql 參考如下:

select min(id) from follow_fans_1 where biz_content = #{bizContent}


由于表中數(shù)據(jù)量太大,每個表中總數(shù)據(jù)量都是上億級別,導(dǎo)致第一步查詢 minId就直接超時了,根本沒有機(jī)會去執(zhí)行第二步。但是考慮到上一個查詢方案只有最后一頁才會查詢超時,前N-1頁查詢根本用不到 minId 作為區(qū)間限制。所以當(dāng)表中數(shù)據(jù)量很大時,通常從第一頁到最后一頁查詢之間會存在一定的時間差。我們就可以正好去利用這個時間差去異步查詢minId,然后將查詢出來的minId存儲到緩存中,考慮到這個 minId 可能會被刪除,可以設(shè)置一定的過期時間。最后優(yōu)化后的查詢流程如下:

  1. 調(diào)用查詢粉絲列表方法時首先查詢緩存minId;
  2. 如果緩存minId 為空,則創(chuàng)建異步任務(wù)去執(zhí)行select min(id) 查詢表中的 minId,然后回寫緩存,該異步任務(wù)執(zhí)行時間可能會很長,可以單獨(dú)設(shè)置超時時間。
  3. 如果緩存minId不為空,則在查詢sql中拼接查詢條件id >={minId},從而保證查詢最后一頁時不會超時。

但是在上述方案中,如果表中的數(shù)據(jù)量達(dá)到上億級別時,第二步的異步獲取minId任務(wù)還是會存在超時的風(fēng)險,從而導(dǎo)致查詢最后一頁粉絲列表出現(xiàn)超時。所以我們又引入了離線數(shù)據(jù)計算任務(wù),通過在大數(shù)據(jù)平臺離線計算獲取每個biz_content下的minId,然后將計算結(jié)果minId推送到緩存中。為了保證minId能夠及時更新,我們可以自由設(shè)置該離線任務(wù)的執(zhí)行周期,比如每周執(zhí)行一次。通過大數(shù)據(jù)平臺的離線計算minId,從而大大減少了在查詢粉絲列表時執(zhí)行 select min(id)的業(yè)務(wù)數(shù)據(jù)庫壓力。只有當(dāng)緩存沒有命中的時候才去執(zhí)行 select min(id),通常這些緩存沒有命中的 minId 也都是一些被離線任務(wù)遺漏的少量數(shù)據(jù),不會影響接口的整體查詢性能。

  • 方案優(yōu)點(diǎn):避免了數(shù)據(jù)量變大時,頁碼查詢深入的性能下降問題;經(jīng)過接口壓測,千萬級數(shù)據(jù)量時,從第一頁到最后一頁都控制在幾十毫秒內(nèi)。
  • 方案缺點(diǎn):只能支持按照頁碼順序和主鍵ID倒序查詢,不支持跳頁查詢,并且還需要依賴大數(shù)據(jù)平臺離線計算和額外的緩存來存儲 minId。

三、對SQL優(yōu)化治理的思考

通過對以上三種方案的探索實(shí)踐,發(fā)現(xiàn)每一種方案都有自己的優(yōu)缺點(diǎn)和它的適用場景,我們不能脫離實(shí)際業(yè)務(wù)場景去談方案的好壞。所以我們要結(jié)合實(shí)際的業(yè)務(wù)環(huán)境以及表中數(shù)據(jù)量的大小去綜合考慮、權(quán)衡利弊,然后找到更適合的技術(shù)方案。以下是總結(jié)的幾條SQL優(yōu)化建議:

查詢條件一定要有索引

索引主要分為兩大類,聚簇索引和非聚簇索引,可以通過 explain 查看 sql 執(zhí)行計劃判斷查詢是否使用了索引。

聚簇索引 (clustered index):聚簇索引的葉子節(jié)點(diǎn)存儲行記錄,InnoDB必須要有且只有一個聚簇索引:

  1. 如果表定義了主鍵,則主鍵索引就是聚簇索引;
  2. 如果沒有定義主鍵,則第一個非空的唯一索引列是聚簇索引;
  3. 如果沒有唯一索引,則創(chuàng)建一個隱藏的row-id列作為聚簇索引。主鍵索引查詢非??欤梢灾苯佣ㄎ恍杏涗?。

非聚簇索引 (secondary index):InnoDB非聚簇索引的葉子節(jié)點(diǎn)存儲的是行記錄的主鍵值,而MyISAM葉子節(jié)點(diǎn)存儲的是行指針。 通常情況下,需要先遍歷非聚簇索引獲得聚簇索引的主鍵ID,然后在遍歷聚簇索引獲取對應(yīng)行記錄。

正確使用索引,防止索引失效

可以參考以下幾點(diǎn)索引原則:

  1. 最左前綴匹配原則,mysql會一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如 a=1 and b=2 and c>3 and d=4 ,如果建立了(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a、b、d的順序可以任意調(diào)整。
  2. =和in可以亂序,比如 a=1 and b=2 and c=3 建立(a,b,c)索引可以任意順序,mysql的查詢優(yōu)化器會幫助優(yōu)化成索引可以識別的形式。
  3. 盡量選擇區(qū)分度高德列作為索引,區(qū)分度公式count(distinct col)/count(*),表示字段不重復(fù)的比例。
  4. 索引列不能使用函數(shù)或參與計算,不能進(jìn)行類型轉(zhuǎn)換,否則索引會失效。
  5. 盡量擴(kuò)展索引,不要新建索引。

減少查詢字段,避免回表查詢

回表查詢就是先定位主鍵值,在根據(jù)主鍵值定位行記錄,需要掃描兩遍索引。 解決方案:只需要在一顆索引樹上能夠獲取SQL所需要的所有列數(shù)據(jù),則無需回表查詢,速度更快??梢詫⒁樵兊淖侄危⒌铰?lián)合索引里去,這就是索引覆蓋。查詢sql在進(jìn)行explain解析時,Extra字段為Using Index時,則觸發(fā)索引覆蓋。沒有觸發(fā)索引覆蓋,發(fā)生了回表查詢時,Extra字段為Using Index condition。

作者:京東零售 曹志飛

來源:京東云開發(fā)者社區(qū) 轉(zhuǎn)載請注明來源文章來源地址http://www.zghlxwxcb.cn/news/detail-665990.html

到了這里,關(guān)于千萬級數(shù)據(jù)深分頁查詢SQL性能優(yōu)化實(shí)踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 阿里二面:千萬級、億級數(shù)據(jù),如何性能優(yōu)化? 教科書級 答案來了

    阿里二面:千萬級、億級數(shù)據(jù),如何性能優(yōu)化? 教科書級 答案來了

    在尼恩指導(dǎo)了幾百個小伙伴的面試,在這些過程中, 非常、非常高頻的一個面試題: 千萬級數(shù)據(jù),如何做性能優(yōu)化? 億級數(shù)據(jù),如何做性能優(yōu)化? 最近,有個小伙伴阿里二面,又遇到了這個問題。 其實(shí),尼恩一直想梳理一個教科書式的答案, 但是由于千萬級數(shù)據(jù)、億級數(shù)

    2024年02月02日
    瀏覽(22)
  • 面試官:Mysql千萬級大表如何進(jìn)行深度分頁優(yōu)化?

    假如有一張千萬級的訂單表,這張表沒有采用分區(qū)分表,也沒有使用ES等技術(shù),分頁查詢進(jìn)行到一定深度分頁之后(比如1000萬行后)查詢比較緩慢,我們該如何進(jìn)行優(yōu)化? 訂單表結(jié)構(gòu)如下: 其中 Mysql 版本為8.0。我們使用Python腳本向表中插入2000萬條數(shù)據(jù)。 導(dǎo)出數(shù)據(jù)時我們需

    2024年02月19日
    瀏覽(22)
  • MySQL千萬級數(shù)據(jù)優(yōu)化方案

    MySQL千萬級數(shù)據(jù)優(yōu)化方案

    ? ? ? ? ? ? ? ? ? ? ? ? ? ↓↓↓處理千萬級數(shù)據(jù)的MySQL數(shù)據(jù)庫,可以采取以下優(yōu)化措施↓↓↓ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 使用索引:確保對經(jīng)常用于查詢和排序的字段添加索引。不要在查詢中使用SELECT *,而是明確指定需要的字段。

    2024年02月07日
    瀏覽(22)
  • EMQX+阿里云飛天洛神云網(wǎng)絡(luò) NLB:MQTT 消息億級并發(fā)、千萬級吞吐性能達(dá)成

    EMQX+阿里云飛天洛神云網(wǎng)絡(luò) NLB:MQTT 消息億級并發(fā)、千萬級吞吐性能達(dá)成

    隨著物聯(lián)網(wǎng)技術(shù)的發(fā)展與各行業(yè)數(shù)字化進(jìn)程的推進(jìn),全球物聯(lián)網(wǎng)設(shè)備連接規(guī)模與日俱增。一個可靠高效的物聯(lián)網(wǎng)系統(tǒng)需要具備高并發(fā)、大吞吐、低時延的數(shù)據(jù)處理能力,支撐海量物聯(lián)網(wǎng)數(shù)據(jù)的接入與分析,從而進(jìn)一步挖掘數(shù)據(jù)價值。 于今年五月發(fā)布的 EMQX 5.0 版本全球首個實(shí)

    2023年04月15日
    瀏覽(23)
  • MySQL千萬數(shù)據(jù)查詢優(yōu)化之路

    本文主要針對 MySQL 在千萬級別數(shù)據(jù)的分頁查詢性能進(jìn)行優(yōu)化, 下面是整個優(yōu)化的過程. 先說結(jié)論, MySQL 在千萬級別數(shù)據(jù)的分頁查詢性能主要受到 2 個因素的影響: 查詢的偏移量 查詢的數(shù)據(jù)量 查詢的偏移量優(yōu)化 當(dāng) MySQL 執(zhí)行查詢語句分頁 LIMIT 時, 有 2 個步驟需要先按照指定的排序

    2023年04月09日
    瀏覽(16)
  • 萬級數(shù)據(jù)優(yōu)化EasyExcel+mybatis流式查詢導(dǎo)出封裝

    萬級數(shù)據(jù)優(yōu)化EasyExcel+mybatis流式查詢導(dǎo)出封裝

    時間 更新內(nèi)容 2023/09/23 fix: 每個sheet大小和存儲內(nèi)存條數(shù)一致的bug update: 增大一個sheet的默認(rèn)容量 我們不妨先給大家講一個概念,利用此概念我們正好給大家介紹一個數(shù)據(jù)庫優(yōu)化的小技巧: 需求如下:將一個地市表的數(shù)據(jù)導(dǎo)出70萬條。 如果你不假思索,直接一條sql語句搞上去

    2024年02月11日
    瀏覽(48)
  • (Oracle)SQL優(yōu)化技巧(一):分頁查詢

    目錄 分頁查詢框架 分頁查詢注意事項(xiàng)? 有序/無序分頁 事務(wù)帶來的影響 分頁查詢與索引 排序字段索引實(shí)驗(yàn) 組合索引實(shí)驗(yàn) 利用ROWNUM進(jìn)行分頁查詢的方法在各版本都是適用的,11g,12c,19c都可以使用該方法哦。在分享分頁查詢方法之前,需要先聊下ROWNUM,這玩意兒要是聊不清楚,

    2024年04月11日
    瀏覽(34)
  • 百萬級sql server數(shù)據(jù)庫優(yōu)化案例分享

    百萬級sql server數(shù)據(jù)庫優(yōu)化案例分享

    ????????在我們的IT職業(yè)生涯中,能有一次百萬級的數(shù)據(jù)庫的優(yōu)化經(jīng)歷是很難得的,如果你遇到了恭喜你,你的職業(yè)生涯將會更加完美,如果你遇到并解決了,那么一定足夠你炫耀很多年。 ? ? ? ? 這里我將要分享一次完美的百萬級數(shù)據(jù)庫優(yōu)化經(jīng)歷,希望能給在IT行業(yè)的小

    2024年02月17日
    瀏覽(92)
  • 百萬數(shù)據(jù)慢慢讀?Pandas性能優(yōu)化法速讀百萬級數(shù)據(jù)無壓力

    作為數(shù)據(jù)分析工作者,我們每天都要處理大量數(shù)據(jù),這時Pandas等工具的讀取性能也就備受關(guān)注。特別是當(dāng)數(shù)據(jù)集達(dá)到百萬行以上時,如何提高讀取效率,讓數(shù)據(jù)分析工作跑上“快車道”?本文將詳細(xì)分析Pandas讀取大數(shù)據(jù)的性能優(yōu)化方法,以及一些建議和經(jīng)驗(yàn)。 1. 使用SQL進(jìn)行預(yù)處理 可

    2024年02月09日
    瀏覽(23)
  • kafka千萬級數(shù)據(jù)積壓原因以及解決方案

    一、原因 kafka作為消息隊(duì)列,其中數(shù)據(jù)積壓也是經(jīng)常遇到的問題之一。 我們都知道,數(shù)據(jù)積壓的直接原因,一定是系統(tǒng)中的某個部分出現(xiàn)了性能問題,來不及處理上游發(fā)送的數(shù)據(jù),才會導(dǎo)致數(shù)據(jù)積壓。 那么我們就需要分析在使用kafka時,如何通過優(yōu)化代碼以及參數(shù)配置來最大

    2024年02月12日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包