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

使用MySQL進(jìn)行千萬級(jí)別數(shù)據(jù)查詢的技巧分享

 更新時(shí)間:2024年03月01日 11:25:05   作者:zy_zeros  
這篇文章主要介紹了如何使用MySQL進(jìn)行千萬級(jí)別數(shù)據(jù)查詢的技巧,文中通過代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

一般分頁

在系統(tǒng)中需要進(jìn)行分頁操作時(shí),我們通常會(huì)使用 LIMIT 加上偏移量的方式實(shí)現(xiàn),語法格式如下。

SELECT … FROM … WHERE … ORDER BY … LIMIT …

在有對(duì)應(yīng)索引的情況下,這種方式一般效率還不錯(cuò)。但它存在一個(gè)讓人頭疼的問題,在偏移量非常大的時(shí)候,也就是翻頁到很靠后的頁面時(shí),查詢速度會(huì)變得越來越慢。

我們來演示一下。

先創(chuàng)建一個(gè)訂單表 t_order。

CREATE TABLE t_order (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘自增主鍵',
order_no varchar(32) NOT NULL COMMENT ‘訂單號(hào)',
user_id varchar(20) NOT NULL COMMENT ‘用戶ID',
amount decimal(18,2) NOT NULL COMMENT ‘訂單金額',
order_status tinyint(4) NOT NULL COMMENT ‘訂單狀態(tài):0新建 1處理中 2成功 3失敗',
create_time datetime NOT NULL COMMENT ‘創(chuàng)建時(shí)間',
PRIMARY KEY (id),
UNIQUE KEY uniq_order_no (order_no) USING BTREE COMMENT ‘訂單號(hào)唯一索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

往表中插入1100w 條數(shù)據(jù)。( t1 是一個(gè)有100條數(shù)據(jù)的表,這里我利用笛卡爾乘積的方式插入1100w條數(shù)據(jù))

set @N=0;
INSERT INTO t_order(order_no,user_id,amount,order_status,create_time)
select
CONCAT(“APP”, @N:=@N+1),
CONCAT(“USER_ID_”, @N+1),
@N%10000,
@N%4,
NOW()
from t1 a, t1 b, t1 c, t1 d
LIMIT 11000000;

我們看下,如下這些查詢花費(fèi)的時(shí)間。

select * from t_order order by id limit 0, 10;
select * from t_order order by id limit 10000, 10;
select * from t_order order by id limit 100000, 10;
select * from t_order order by id limit 1000000, 10;
select * from t_order order by id limit 10000000, 10;

執(zhí)行時(shí)間如下:

– 0.002
– 0.045
– 0.069
– 0.517
– 4.134

同樣是只查詢10條數(shù)據(jù),最開始的時(shí)候查詢花費(fèi) 0.002s,而到最后,查詢花費(fèi)了 4.134s。

這是什么原因呢?

這是因?yàn)椴樵儠r(shí) MySQL 并不是跳過 OFFSET 行,而是取 OFFSET+N 行,然后放棄前 OFFSET 行,最后返回 N 行,當(dāng) OFFSET 特別大的時(shí)候,效率就非常的低下。

拿 limit 10000, 10 這條語句來說明一下, MySQL在執(zhí)行這條查詢的時(shí)候,需要查詢 10010 (10000 + 10) 條記錄,然后只返回最后 10 條,并將前面的 10000 條記錄拋棄,這樣當(dāng)翻頁越靠后時(shí),代價(jià)就變得越來越高。

知道問題所在了,那有什么辦法可以優(yōu)化,解決這個(gè)問題呢?

1優(yōu)化一:記錄位置,避免使用 OFFSET

首先獲取第一頁的結(jié)果:

select * from t_order limit 10;

假如上邊返回的是 id 為1 ~ 10的記錄,我們將 10 這個(gè)值記住,下一頁查詢就可以直接從 10 這個(gè)值開始。

select * from t_order where id > 10 limit 10;

這樣做,無論翻頁到多少頁,性能都會(huì)很好:

select * from t_order limit 10;
select * from t_order where id > 10000 limit 10;
select * from t_order where id > 100000 limit 10;
select * from t_order where id > 1000000 limit 10;
select * from t_order where id > 10000000 limit 10;

執(zhí)行時(shí)間如下:

– 0.003
– 0.005
– 0.002
– 0.002
– 0.002

而如果我們當(dāng)前記錄的 id 值為 10000,我們想查上一頁怎么辦呢?返回去查一下即可:

select * from t_order where id <= 10000 order by id desc limit 10,10;

這種優(yōu)化方式,可以實(shí)現(xiàn)上一頁、下一頁這種的分頁。但如果想要實(shí)現(xiàn)跳轉(zhuǎn)到指定頁碼的話,就需要保證 id 連續(xù)不中斷,再通過計(jì)算找到準(zhǔn)確的位置。

2優(yōu)化二:計(jì)算邊界值,轉(zhuǎn)換為已知位置的查詢

如果 id 連續(xù)不中斷,我們就可以計(jì)算出每一頁的邊界值,讓 MySQL 根據(jù)邊界值進(jìn)行范圍掃描,查出數(shù)據(jù)。

select * from t_order where id between 0 and 10;
select * from t_order where id between 10000 and 10010;
select * from t_order where id between 100000 and 100010;
select * from t_order where id between 1000000 and 1000010;
select * from t_order where id between 10000000 and 10000010;

執(zhí)行時(shí)間如下:

– 0.001
– 0.002
– 0.002
– 0.001
– 0.001

3優(yōu)化三:使用索引覆蓋+子查詢優(yōu)化

先在索引樹中找到開始位置的 id 值,再根據(jù)找到的 id 值查詢行數(shù)據(jù)。

select * from t_order where id >= (select id from t_order order by id limit 0, 1) order by id limit 10;
select * from t_order where id >= (select id from t_order order by id limit 10000, 1) order by id limit 10;
select * from t_order where id >= (select id from t_order order by id limit 100000, 1) order by id limit 10;
select * from t_order where id >= (select id from t_order order by id limit 1000000, 1) order by id limit 10;
select * from t_order where id >= (select id from t_order order by id limit 10000000, 1) order by id limit 10;

執(zhí)行時(shí)間如下:

– 0.007
– 0.009
– 0.047
– 0.332
– 2.822

可以看到,這種優(yōu)化方式也可以提升查詢速度。這其實(shí)是利用了索引覆蓋的如下好處:

索引文件不包含行數(shù)據(jù)的所有信息,故其大小遠(yuǎn)小于數(shù)據(jù)文件,因此可以減少大量的IO操作。

索引覆蓋只需要掃描一次索引樹,不需要回表掃描行數(shù)據(jù),所以性能比回表查詢要高。

4優(yōu)化四:使用索引覆蓋+連接查詢優(yōu)化

這種優(yōu)化方式跟 優(yōu)化三 原理一樣。也是先在索引上進(jìn)行分頁查詢,當(dāng)找到 id 后,再統(tǒng)一通過 JOIN 關(guān)聯(lián)查詢得到最終需要的數(shù)據(jù)詳情。

select * from t_order a Join (select id from t_order order by id limit 0, 10) b ON a.id = b.id;
select * from t_order a Join (select id from t_order order by id limit 10000, 10) b ON a.id = b.id;
select * from t_order a Join (select id from t_order order by id limit 100000, 10) b ON a.id = b.id;
select * from t_order a Join (select id from t_order order by id limit 1000000, 10) b ON a.id = b.id;
select * from t_order a Join (select id from t_order order by id limit 10000000, 10) b ON a.id = b.id;

執(zhí)行時(shí)間如下:

– 0.001
– 0.023
– 0.028
– 0.348
– 2.955

以上就是使用MySQL進(jìn)行千萬級(jí)別數(shù)據(jù)查詢的技巧分享的詳細(xì)內(nèi)容,更多關(guān)于MySQL千萬級(jí)別數(shù)據(jù)查詢的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL系列之七 MySQL存儲(chǔ)引擎

    MySQL系列之七 MySQL存儲(chǔ)引擎

    存儲(chǔ)引擎是數(shù)據(jù)庫的核心,對(duì)于mysql來說,存儲(chǔ)引擎是以插件的形式運(yùn)行的。雖然mysql支持種類繁多的存儲(chǔ)引擎,但是常用的就那么幾種。這篇文章主要給大家介紹MySQL存儲(chǔ)引擎的相關(guān)知識(shí),一起看看吧
    2021-07-07
  • Ubuntu18.04 安裝mysql8.0.11的圖文教程

    Ubuntu18.04 安裝mysql8.0.11的圖文教程

    本文通過圖文并茂的形式給大家介紹了Ubuntu18.04 安裝mysql8.0.11的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧
    2018-07-07
  • mysql行轉(zhuǎn)列(7種方法)和列轉(zhuǎn)行的實(shí)現(xiàn)

    mysql行轉(zhuǎn)列(7種方法)和列轉(zhuǎn)行的實(shí)現(xiàn)

    本文主要介紹了mysql行轉(zhuǎn)列(7種方法)和列轉(zhuǎn)行的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • 淺談MySQL的容量規(guī)劃

    淺談MySQL的容量規(guī)劃

    進(jìn)行MySQL的容量規(guī)劃是確保數(shù)據(jù)庫能夠在當(dāng)前和未來的負(fù)載下順利運(yùn)行的重要步驟,容量規(guī)劃包括評(píng)估當(dāng)前資源使用情況、預(yù)測(cè)未來增長(zhǎng)、調(diào)整配置和硬件資源等,感興趣的可以了解一下
    2025-08-08
  • 解析MySQL隱式轉(zhuǎn)換問題

    解析MySQL隱式轉(zhuǎn)換問題

    本文通過實(shí)例代碼給大家介紹了MySQL隱式轉(zhuǎn)換問題,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • MySQL排序與分頁講解

    MySQL排序與分頁講解

    這篇文章主要介紹了MySQL排序與分頁講解,使用 ORDER BY 對(duì)查詢到的數(shù)據(jù)進(jìn)行排序操作,按照dept_id的降序排列,salary的升序排列相關(guān)展開文章,需要的小伙伴可以參考一下
    2022-01-01
  • MYSQL SET類型字段的SQL操作知識(shí)介紹

    MYSQL SET類型字段的SQL操作知識(shí)介紹

    本篇文章是對(duì)MYSQL中SET類型字段的SQL操作知識(shí)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • K8s 如何部署 MySQL 8.0.20 主從復(fù)制結(jié)構(gòu)

    K8s 如何部署 MySQL 8.0.20 主從復(fù)制結(jié)構(gòu)

    這篇文章主要介紹了K8s 如何部署 MySQL 8.0.20 主從復(fù)制結(jié)構(gòu),本次使用 OpenEBS 來作為存儲(chǔ)引擎,OpenEBS 是一個(gè)開源的、可擴(kuò)展的存儲(chǔ)平臺(tái),它提供了一種簡(jiǎn)單的方式來創(chuàng)建和管理持久化存儲(chǔ)卷,需要的朋友可以參考下
    2024-04-04
  • MySQL中order?by排序語句的原理解析

    MySQL中order?by排序語句的原理解析

    這篇文章主要介紹了MySQL中order?by排序語句的原理,本文結(jié)合示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • MySql存儲(chǔ)過程循環(huán)的使用分析詳解

    MySql存儲(chǔ)過程循環(huán)的使用分析詳解

    這篇文章主要介紹了MySql存儲(chǔ)過程循環(huán)的使用分析詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下
    2022-06-06

最新評(píng)論

育儿| 苍南县| 蓬安县| 界首市| 威宁| 云龙县| 鹤山市| 景德镇市| 大田县| 连城县| 德惠市| 余庆县| 东乡族自治县| 澜沧| 大安市| 南丰县| 安西县| 东宁县| 深州市| 青铜峡市| 莱西市| 响水县| 寿阳县| 鄂伦春自治旗| 洛扎县| 钟山县| 合江县| 鸡东县| 锡林浩特市| 睢宁县| 盈江县| 抚州市| 锦屏县| 郧西县| 乐东| 沙洋县| 芜湖市| 华阴市| 沁阳市| 石景山区| 成武县|