在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

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

京東云 ? 來源:京東零售 曹志飛 ? 作者:京東零售 曹志飛 ? 2024-10-30 10:49 ? 次閱讀

作者:京東零售 曹志飛

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

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

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

數(shù)據(jù)庫表結構示例如下:

CREATE TABLE follow_fans_[0-255]
  (
    id bigint(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
    biz_content   VARCHAR(50) DEFAULT NULL COMMENT '業(yè)務對象ID',
    source        VARCHAR(50) DEFAULT NULL COMMENT '來源',
    pin           VARCHAR(50) DEFAULT NULL COMMENT '用戶pin',
    ext           VARCHAR(5000) DEFAULT NULL COMMENT '擴展信息',
    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 = '關注粉絲表';

Limit實現(xiàn)

由于同一個業(yè)務對象的所有粉絲都保存到一張數(shù)據(jù)庫表中,對于分頁查詢列表接口,首先想到的就是用limit實現(xiàn),對于粉絲數(shù)量很少的關注對象,查詢接口性能還不錯。但是隨著關注對象的粉絲數(shù)量越來越多,接口查詢性能就會越來越慢。后來經(jīng)過接口壓測,當業(yè)務對象粉絲列表數(shù)量達到幾十萬級別的時候,查詢頁碼數(shù)量越大,查詢耗時越多。limit深分頁為什么會變慢?這就和sql的執(zhí)行計劃有關了,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)點:實現(xiàn)簡單,支持跳頁查詢。

?方案缺點:數(shù)據(jù)量變大時,隨著查詢頁碼的深入,查詢性能越來越差。

標簽記錄法

Limit深分頁問題的本質原因就是:偏移量(offset)越大,mysql就會掃描越多的行,然后再拋棄掉,這樣就導致查詢性能的下降。所以我們可以采用標簽記錄法,就是標記一下上次查詢到哪一條了,下次再來查的時候,從該條開始往下掃描。具體做法方式是,查詢粉絲列表中按照自增主鍵ID倒序查詢,查詢結果中返回主鍵ID,然后查詢入?yún)⒅性黾觤axId參數(shù),該參數(shù)需要透傳上一次請求粉絲列表中最后一條記錄主鍵ID,第一次查詢時可以為空,但是需要查詢下一頁時就必傳。最后根據(jù)查詢時返回的行數(shù)是否等于 10 來判斷整個查詢是否可以結束。優(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)點:避免了數(shù)據(jù)量變大時,頁碼查詢深入的性能下降問題;經(jīng)過接口壓測,千萬級數(shù)據(jù)量時,前 N-1頁查詢耗時可以控制在幾十毫秒內。

?方案缺點:只能支持按照頁碼順序查詢,不支持跳頁,而且僅能保證前 N-1 頁的查詢性能;如果最后一頁的表中行數(shù)量不滿 10 條時,引擎不知道何時終止查詢,只能遍歷全表,所以當表中數(shù)據(jù)量很大時,還是會出現(xiàn)超時情況。

區(qū)間限制法

標簽記錄法最后一頁查詢超時就是因為不知道何時終止查詢,所以我們可以提供一個區(qū)間限制范圍來告訴引擎查詢到此結束。

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

1.調用查詢粉絲列表方法時首先查詢緩存minId;

2.如果緩存minId 為空,則創(chuàng)建異步任務去執(zhí)行select min(id) 查詢表中的 minId,然后回寫緩存,該異步任務執(zhí)行時間可能會很長,可以單獨設置超時時間。

3.如果緩存minId不為空,則在查詢sql中拼接查詢條件id >={minId},從而保證查詢最后一頁時不會超時。

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

?方案優(yōu)點:避免了數(shù)據(jù)量變大時,頁碼查詢深入的性能下降問題;經(jīng)過接口壓測,千萬級數(shù)據(jù)量時,從第一頁到最后一頁都控制在幾十毫秒內。

?方案缺點:只能支持按照頁碼順序和主鍵ID倒序查詢,不支持跳頁查詢,并且還需要依賴大數(shù)據(jù)平臺離線計算和額外的緩存來存儲 minId。

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

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

查詢條件一定要有索引

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

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

1.如果表定義了主鍵,則主鍵索引就是聚簇索引;

2.如果沒有定義主鍵,則第一個非空的唯一索引列是聚簇索引;

3.如果沒有唯一索引,則創(chuàng)建一個隱藏的row-id列作為聚簇索引。主鍵索引查詢非常快,可以直接定位行記錄。

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

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

可以參考以下幾點索引原則:

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的順序可以任意調整。

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(*),表示字段不重復的比例。

4.索引列不能使用函數(shù)或參與計算,不能進行類型轉換,否則索引會失效。

5.盡量擴展索引,不要新建索引。

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

回表查詢就是先定位主鍵值,在根據(jù)主鍵值定位行記錄,需要掃描兩遍索引。 解決方案:只需要在一顆索引樹上能夠獲取SQL所需要的所有列數(shù)據(jù),則無需回表查詢,速度更快。可以將要查詢的字段,建立到聯(lián)合索引里去,這就是索引覆蓋。查詢sql在進行explain解析時,Extra字段為Using Index時,則觸發(fā)索引覆蓋。沒有觸發(fā)索引覆蓋,發(fā)生了回表查詢時,Extra字段為Using Index condition。

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • SQL
    SQL
    +關注

    關注

    1

    文章

    779

    瀏覽量

    44697
  • 定位
    +關注

    關注

    5

    文章

    1381

    瀏覽量

    35756
收藏 人收藏

    評論

    相關推薦

    2017雙11技術揭秘—TDDL/DRDS 的類 KV 查詢優(yōu)化實踐

    摘要: 性能優(yōu)化是企業(yè)級應用永恒的話題,關系型數(shù)據(jù)查詢優(yōu)化更是如此。在前臺核心業(yè)務場景中,類 KeyValue
    發(fā)表于 12-29 14:29

    JPA分頁查詢的常用方法

    JPA分頁查詢與條件分頁查詢
    發(fā)表于 10-23 17:10

    數(shù)據(jù)庫設計及開發(fā)規(guī)范之sql性能優(yōu)化

    數(shù)據(jù)庫設計及開發(fā)規(guī)范,sql性能優(yōu)化
    發(fā)表于 05-08 10:58

    基于KingView的SQL數(shù)據(jù)查詢設計_楊洋

    基于KingView的SQL數(shù)據(jù)查詢設計_楊洋
    發(fā)表于 01-17 19:57 ?1次下載

    SQL優(yōu)化器原理 - 查詢優(yōu)化器綜述

    摘要:?本文主要是對數(shù)據(jù)查詢優(yōu)化器的一個綜述,包括查詢優(yōu)化器分類、查詢
    發(fā)表于 07-24 17:38 ?366次閱讀
    <b class='flag-5'>SQL</b><b class='flag-5'>優(yōu)化</b>器原理 - <b class='flag-5'>查詢</b><b class='flag-5'>優(yōu)化</b>器綜述

    百億級數(shù)據(jù)分表后 怎樣才能分頁查詢

    比如分頁查詢的問題。一般我們把分表的字段稱作shardingkey,比如訂單表按照用戶ID作為shardingkey,那么如果查詢條件中不帶用戶ID查詢怎么做
    的頭像 發(fā)表于 11-19 15:43 ?1638次閱讀
    百億<b class='flag-5'>級數(shù)據(jù)</b>分表后 怎樣才能<b class='flag-5'>分頁</b><b class='flag-5'>查詢</b>

    SQL查詢優(yōu)化是怎么回事

    查詢 (Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點之一。 關聯(lián)子查詢的基本
    的頭像 發(fā)表于 02-01 13:55 ?2208次閱讀
    <b class='flag-5'>SQL</b>子<b class='flag-5'>查詢</b><b class='flag-5'>優(yōu)化</b>是怎么回事

    MyBatis流式查詢輕松幫你解決分頁慢的問題

    結果。流式查詢的好處是能夠降低內存使用。 如果沒有流式查詢,我們想要從數(shù)據(jù)庫取 1000 萬條記錄而又沒有足夠的內存時,就不得不分頁查詢,而
    的頭像 發(fā)表于 08-04 15:52 ?4414次閱讀

    如何優(yōu)化MySQL百萬數(shù)據(jù)分頁問題

    我們日常做分頁需求時,一般會用limit實現(xiàn),但是當偏移量特別大的時候,查詢效率就變得低下。本文將分四個方案,討論如何優(yōu)化MySQL百萬數(shù)據(jù)
    的頭像 發(fā)表于 04-06 15:12 ?2027次閱讀

    sql優(yōu)化常用的幾種方法

    前言 1.慢SQL優(yōu)化思路。 1.1 慢查詢日志記錄慢SQL 1.2 explain查看分析SQL的執(zhí)行計劃 1.3 profile 分析執(zhí)
    的頭像 發(fā)表于 11-14 15:04 ?5732次閱讀

    一文終結SQL查詢優(yōu)化

    查詢(Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點之一。關聯(lián)子查詢的基本執(zhí)行
    的頭像 發(fā)表于 04-28 14:19 ?907次閱讀
    一文終結<b class='flag-5'>SQL</b>子<b class='flag-5'>查詢</b><b class='flag-5'>優(yōu)化</b>

    sql語句where條件查詢

    的細節(jié),包括使用的操作符、條件的組合、多張表的查詢、條件的性能優(yōu)化等方面。 首先,讓我們了解一下WHERE子句中常用的操作符。在SQL中,常用的操作符包括: 比較操作符: 等于(=):
    的頭像 發(fā)表于 11-23 11:28 ?1448次閱讀

    oracle執(zhí)行sql查詢語句的步驟是什么

    Oracle數(shù)據(jù)庫是一種常用的關系型數(shù)據(jù)庫管理系統(tǒng),具有強大的SQL查詢功能。Oracle執(zhí)行SQL查詢
    的頭像 發(fā)表于 12-06 10:49 ?1200次閱讀

    SQL改寫消除相關子查詢實踐

    GaussDB (DWS) 根據(jù)子查詢SQL 語句中的位置把子查詢分成了子查詢、子鏈接兩種形式。
    的頭像 發(fā)表于 12-27 09:51 ?641次閱讀

    數(shù)據(jù)從業(yè)者必知必會的Hive SQL調優(yōu)技巧

    數(shù)據(jù)從業(yè)者必知必會的Hive SQL調優(yōu)技巧 摘要 :在大數(shù)據(jù)領域中,Hive SQL被廣泛應用于數(shù)據(jù)倉庫的
    的頭像 發(fā)表于 09-24 13:30 ?525次閱讀
    主站蜘蛛池模板: 中文一级黄色片 | 最好看的最新中文字幕2018免费视频 | 亚洲视频第一页 | 日本黄色一区 | 国产精品视频一区二区三区 | 加勒比啪啪 | 国产精品理论 | 色多多免费视频 | 在线网址你懂的 | 天天爱天天干天天操 | 99久久婷婷国产综合精品电影 | 亚洲综合一二三区 | 午夜视频1000 | 女bbbbxxxx另类亚洲 | 最新eeuss影院第256页 | 全午夜免费一级毛片 | 狠狠操操| 亚洲成人综合网站 | 女人大毛片一级毛片一 | 99久久99久久免费精品蜜桃 | 一级特黄a免费大片 | 日韩欧美伦理 | 久久婷婷色综合老司机 | 黑人一区二区三区中文字幕 | 亚洲黄色性视频 | 三级视频中文字幕 | 爱搞逼综合 | 免费一级欧美片在线观看 | 永久免费品色堂 | 天堂8中文在线最新版在线 天堂8资源8在线 | 人人爱爱| 久久波多野结衣 | 成人欧美网站 | 无遮挡高清一级毛片免费 | bt天堂在线www中文在线 | 婷婷毛片| 好爽好深太大了再快一点 | 亚洲色图在线观看视频 | 婷婷成人丁香五月综合激情 | 97影院午夜在线观看视频 | 美女毛片免费看 |