日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MYSQL深度分页的常见优化方案

發(fā)布時間:2024/1/18 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MYSQL深度分页的常见优化方案 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、分頁查詢:一般寫法

一個比較常見的寫法

SELECT * FROM tableName where kid=1342 and type=1 order id asc limit 149420, 20;

該SQL是一個經(jīng)典的排序+分頁查詢

order by col limit N,M

MySQL 執(zhí)行此類SQL時需要先掃描到N行,然后再去取M行。對于此類操作,獲取前面少數(shù)幾行數(shù)據(jù)會很快,但是隨著掃描的記錄數(shù)越多,SQL的性能就會越差,因為N的值越大,MySQL需要掃描越多的數(shù)據(jù)來定位到具體的N行,這樣耗費大量的 IO 成本和時間成本。

舉例說明

-- 表名:user -- 主鍵:id -- 索引:key idx_uid_type(uid, type) select * from user where uid =3 and type=1 order by id desc 8,2;

MySQL 是如何執(zhí)行上面的sql 的? 對于Innodb表,系統(tǒng)是根據(jù) idx_uid_type二級索引里面包含的主鍵去查找對應(yīng)的行,也就是會通過主鍵在進行一次回表查詢。

對于百萬千萬級別的數(shù)據(jù)而言,索引大小可能和數(shù)據(jù)大小相差無幾,cache在內(nèi)存中的索引數(shù)量有限,而且二級索引和數(shù)據(jù)葉子節(jié)點不在同一個物理塊兒上存儲,二級索引與主鍵的相對無序映射關(guān)系,也會帶來大量的隨機IO請求,N值越大越需要遍歷大量索引頁和數(shù)據(jù)葉,需要耗費的時間就越久。

我們來思考一個問題,是否需要完全遍歷“無效的數(shù)據(jù)”?如果我們需要limit 8,2;我們跳過前面8行無關(guān)的數(shù)據(jù)頁遍歷,可以直接通過索引定位到第9,第10行,這樣操作是不是更快了?

2、分頁查詢:延遲關(guān)聯(lián)查詢

核心思思:通過使用覆蓋索引查詢返回需要的主鍵,再根據(jù)主鍵關(guān)聯(lián)原表獲得需要的數(shù)據(jù),而不是通過二級索引獲取主鍵,再通過主鍵去遍歷數(shù)據(jù)頁(回表)。

SELECT a.id as id, clientid, adminid, kdtid, type, token, createdtime, updatetime, isvalid, version FROM t1 a, (SELECT id FROM t1 WHERE 1 and client_id = 'xxx' and is_valid= '1' order by kdt_id asc limit 267100,100 ) b WHERE a.id = b.id;

上述SQL中的子查詢只取主鍵id,可避免通過二級索引中的主鍵去回表查詢,這樣性能會快一些。

像上述案例,當offset變得超級大時,會引發(fā)一個問題,它有一個專門的術(shù)語,叫深度分頁。

深度分頁問題,是個很惡心的問題,其惡心之處,在于這個問題,它其實無解。目前不管是mysql還是es都沒有很好的方法去解決這個問題。只能通過限制查詢數(shù)量或分批獲取的方式進行規(guī)避。

3、分頁查詢:基于上次最新主鍵查詢

核心思想:通過主鍵索引,每次定位到id在哪,然后往后遍歷N個數(shù)據(jù),這樣不管是多少數(shù)據(jù),查詢性能都很穩(wěn)定。將所有數(shù)據(jù)根據(jù)主鍵id進行排序,然后分批次取,將當前批次的最大id作為下次篩選的條件進行查詢。

針對上面的延遲關(guān)聯(lián)查詢案例,我們使用基于上次最新主鍵查詢來進行優(yōu)化,如下:

SELECT * FROM t1 where clientid='xxxxx' and isvalid=1 and id<47399727 order by id desc LIMIT 100;

一般情況下該方式有如下兩步:
首先,要獲取復合條件的記錄的最大id和最小id(默認id是主鍵)

select max(id) as maxid ,min(id) as minid from t where kid=2333 and type=1;

其次,根據(jù)id大于最小值或者小于最大值 進行遍歷。

select xx,xx from t where kid=2333 and type=1 and id >=min_id order by id asc limit 100; select xx,xx from t where kid=2333 and type=1 and id <=max_id order by id desc limit 100;

4、小結(jié)

從上面的案例來講,基于上次最新主鍵查詢的方式直接定位到主鍵起始位點,然后過濾所需要的數(shù)據(jù), 相對比延遲關(guān)聯(lián)查詢的方式,其查詢速度更快些,查找數(shù)據(jù)的時候少了二級索引掃描。

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

總結(jié)

以上是生活随笔為你收集整理的MYSQL深度分页的常见优化方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。