精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

帶你讀 MySQL 源碼:Limit,Offset

數(shù)據(jù)庫 MySQL
從 LimitOffsetIterator::Read() 的實現(xiàn)邏輯來看,offset 越大,讀取之后被丟棄的記錄就越多,讀取這些記錄所做的都是無用功。

我一直想寫 MySQL 源碼分析文章,希望能夠達成 2 個目標:

  • 不想研究源碼的朋友,可以通過文章了解 MySQL 常用功能的實現(xiàn)邏輯,做到知其然,也知其所以然。
  • 想研究源碼的朋友,能夠以文章為切入點,邁進 MySQL 源碼研究之門。

目標是明確的,任務(wù)是艱巨的。

MySQL 源碼數(shù)量龐大,各種功能的代碼盤根錯節(jié),相互交織在一起,形成一張復(fù)雜的網(wǎng)。

想要把這張網(wǎng)中的某些部分拎出來寫成文章,還要做到通俗易懂,這并不是件容易的事,我也就遲遲沒有動手。

萬事開頭難,但是再難,總得開始,才能有后續(xù),所以,就有了這篇文章。

寫文章是件費時費力的事,寫出來了總希望有更多人看,否則就沒有寫下去的動力了。

對 MySQL 源碼感興趣的朋友們,如果想看到源碼分析系列的更多文章,請幫忙把文章傳播出去,分享給更多人。

嘮叨完前因后果,再說說我準備怎么寫這個系列文章:

  • 我會挑一些常用功能,每篇文章介紹一個單點功能的源碼,從簡單功能開始,逐漸過渡到復(fù)雜功能。
  • 每篇文章只會介紹核心源碼邏輯,源碼之中增加注釋,源碼之外盡可能用文字展開介紹源碼邏輯,以幫助大家更好的理解源碼。
  • 每篇文章不會太長,如果功能復(fù)雜導(dǎo)致內(nèi)容太長,我會拆分文章,盡量降低大家的閱讀負擔。

接下來,我們開始源碼分析系列的第 1 篇文章。

本文內(nèi)容基于 MySQL 8.0.32 源碼。

正文

1、準備工作

創(chuàng)建測試表:

CREATE TABLE `t1` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`str1` varchar(255) NOT NULL DEFAULT '',
`i1` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

插入測試數(shù)據(jù):

INSERT INTO t1(id, str1, i1) VALUES
(1, 's1', 10),
(2, 's2', 20),
(3, 's3', 30),
(4, 's4', 40),
(5, 's5', 50),
(6, 's6', 60),
(7, 's7', 70),
(8, 's8', 80);

示例 SQL:

select * from t1 limit 5, 2

2、整體介紹

我們先通過 explain 來看一下執(zhí)行計劃:

圖片

從 explain 輸出可以看到,執(zhí)行計劃比較簡單,SQL 執(zhí)行過程包含 2 個迭代器:

  • Limit/Offset,對應(yīng) LimitOffsetIterator 迭代器。
  • Table scan,對應(yīng) TableScanIterator 迭代器。

代碼執(zhí)行時堆棧如下:

| > handle_connection(void*) sql/conn_handler/connection_handler_per_thread.cc:302
| + > do_command(THD*) sql/sql_parse.cc:1439
| + - > dispatch_command(...) sql/sql_parse.cc:2036
| + - x > dispatch_sql_command(THD*, Parser_state*) sql/sql_parse.cc:5322
| + - x = > mysql_execute_command(THD*, bool) sql/sql_parse.cc:4688
| + - x = | > Sql_cmd_dml::execute(THD*) sql/sql_select.cc:578
| + - x = | + > Sql_cmd_dml::execute_inner(THD*) sql/sql_select.cc:778
| + - x = | + - > Query_expression::execute(THD*) sql/sql_union.cc:1823
| + - x = | + - x > // 查詢?nèi)肟?br>| + - x = | + - x > Query_expression::ExecuteIteratorQuery(THD*) sql/sql_union.cc:1770
| + - x = | + - x = > // 實現(xiàn) limit, offset
| + - x = | + - x = > LimitOffsetIterator::Read() sql/iterators/composite_iterators.cc:128
| + - x = | + - x = | > // 從存儲引擎讀取一條記錄
| + - x = | + - x = | > TableScanIterator::Read() sql/iterators/basic_row_iterators.cc:218

3、源碼分析

TableScanIterator 迭代器用于從存儲引擎讀取記錄,留到以后的文章介紹。

limit, offset 由 LimitOffsetIterator 迭代器實現(xiàn),我們會介紹兩個方法的代碼:

  • Query_expression::ExecuteIteratorQuery(THD*),這是查詢?nèi)肟诜椒ǎ榻B了它,流程才算完整。
  • LimitOffsetIterator::Read(),limit, offset 的邏輯都在這個方法里實現(xiàn)。

(1)ExecuteIteratorQuery()

// sql/sql_union.cc
bool Query_expression::ExecuteIteratorQuery(THD *thd) {
...
{
...
for (;;) {
// 從存儲引擎讀取一條記錄
int error = m_root_iterator->Read();
DBUG_EXECUTE_IF("bug13822652_1", thd->killed = THD::KILL_QUERY;);

// 讀取出錯,直接返回
if (error > 0 || thd->is_error()) // Fatal error
return true;
// error < 0
// 表示已經(jīng)讀完了所有符合條件的記錄
// 查詢結(jié)束
else if (error < 0)
break;
// SQL 被客戶端干掉了
else if (thd->killed) // Aborted by user
{
thd->send_kill_message();
return true;
}
...
// 發(fā)送數(shù)據(jù)給客戶端
if (query_result->send_data(thd, *fields)) {
return true;
}
...
}
}
...
}

從以上代碼可以看到,select 查詢?nèi)肟诜椒ǖ闹黧w是一個無限 for 循環(huán)。

每一輪循環(huán)都會調(diào)用 m_root_iterator->Read() 方法從存儲引擎讀取一條記錄。

對于示例 SQL 來說,m_root_iterator->Read() 就是 LimitOffsetIterator::Read()。

for 循環(huán)會一直執(zhí)行,直到 m_root_iterator->Read() 的返回值命中以下任意一個條件才會結(jié)束:

  • if (error > 0 || thd->is_error()),讀取出錯了,以錯誤狀態(tài)結(jié)束查詢。
  • if (error < 0),已經(jīng)讀完所有符合條件的記錄,以正常狀態(tài)結(jié)束查詢。
  • if (thd->killed),SQL 被客戶端通過 kill <query_id> 干掉了,中止查詢。

<query_id> 為 show processlist 中的 Id 字段。

  • for 循環(huán)中,每次從存儲引擎讀取到一條記錄,都會調(diào)用 query_result->send_data(thd, *fields) 方法。

對于示例 SQL 來說,這個方法的行為就是把記錄發(fā)送給客戶端。

(2)LimitOffsetIterator::Read()

// sql/iterators/composite_iterators.cc
int LimitOffsetIterator::Read() {
// 這個 if 括號里的條件理解起來會有點困難
// 所以被省略了,眼不見為凈
//【重點】只有讀取第一條和最后一條記錄時才會進入這個 if 分支
if (...) {
...
// m_needs_offset = true
// 表示 SQL 語句中指定了 offset
if (m_needs_offset) {
...
// 循環(huán)從存儲引擎讀取 m_offset 條記錄
// 每讀取到一條記錄,直接丟棄
for (ha_rows row_idx = 0; row_idx < m_offset; ++row_idx) {
// 讀取一條記錄之后
// 如果沒有出錯,就接著讀取下一條記錄
int err = m_source->Read();
// 讀取出錯,直接返回錯誤碼
if (err != 0) {
return err;
}
...
}
// 讀取 m_offset 條記錄并丟棄之后
// 把 m_seen_rows 設(shè)置為已讀取記錄數(shù)
m_seen_rows = m_offset;
// 然后把 m_needs_offset 設(shè)置為 false
// 表示不需要再處理 offset 邏輯了(因為已處理完成)
// 下次讀取時也就不需要再跳過 m_offset 條記錄了
m_needs_offset = false;
...
}
// 如果已經(jīng)讀取了 m_limit 條記錄
// 就返回 -1,表示讀取結(jié)束
// m_limit = SQL 中的 limit + offset
if (m_seen_rows >= m_limit) {
...
return -1;
}
}

// 讀取需要返回給客戶端的記錄
const int result = m_source->Read();
...
// 已讀取記錄數(shù)加 1
++m_seen_rows;
// 返回當前讀取的記錄
// 給 Query_expression::ExecuteIteratorQuery() 方法
return result;
}

除了處理 offset 邏輯之外,LimitOffsetIterator::Read() 每次只讀取一條記錄,這個方法的核心邏輯分為三部分:

第 1 部分:if (m_needs_offset),SQL 語句中指定了 offset,返回第一條記錄給客戶端之前,需要讀取 offset 條記錄并丟棄,從第 offset + 1 條記錄開始返回給客戶端。

這部分的主要邏輯是一個 for 循環(huán),會循環(huán) offset 次,每次讀取一條記錄。

如果讀取成功,就接著讀取下一條記錄,而不會對這條記錄做任何操作,也就相當于丟棄了。

如果讀取失敗,直接返回錯誤碼,讀取結(jié)束,客戶端會收到報錯信息。

第 2 部分:if (m_seen_rows >= m_limit),表示已經(jīng)讀取了 m_limit 條記錄,返回 -1 表示讀取正常結(jié)束。

m_limit = SQL 中的 limit + offset。

第 3 部分:result = m_source->Read() 從存儲引擎讀取一條記錄,然后,把結(jié)果返回給 Query_expression::ExecuteIteratorQuery() 方法。

4、總結(jié)

limit, offset 邏輯比較簡單,全部由 LimitOffsetIterator::Read() 實現(xiàn),核心邏輯總結(jié)如下:

  • 從存儲引擎讀取返回給客戶端的第 1 條記錄之前,會先讀取 offset 條記錄并丟棄,然后再讀取一條記錄,用于返回給客戶端。
  • 從存儲引擎讀取第 2 ~ limit + offset 條記錄時,每讀取一條記錄,都返回給 Query_expression::ExecuteIteratorQuery(),由該方法把記錄返回給客戶端。
  • 讀取 limit + offset 條記錄之后,返回 -1 表示讀取流程正常結(jié)束。

從 LimitOffsetIterator::Read() 的實現(xiàn)邏輯來看,offset 越大,讀取之后被丟棄的記錄就越多,讀取這些記錄所做的都是無用功。

為了提高 SQL 的執(zhí)行效率,可以通過改寫 SQL 讓 offset 盡可能小,理想狀態(tài)是 offset = 0。

本文轉(zhuǎn)載自微信公眾號「一樹一溪」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系一樹一溪公眾號。

責任編輯:姜華 來源: 一樹一溪
相關(guān)推薦

2023-04-17 08:19:47

select *MySQL

2023-05-26 14:08:00

Where 條件MySQL

2022-10-27 21:34:28

數(shù)據(jù)庫機器學習架構(gòu)

2021-06-09 06:41:11

OFFSETLIMIT分頁

2025-09-26 07:46:07

2022-09-07 07:37:06

LIMITOFFSET分頁

2020-09-18 07:01:38

分頁offsetlimit

2020-08-06 08:00:51

數(shù)據(jù)分頁優(yōu)化

2022-09-09 19:01:02

接口Reader?Spark

2024-10-07 10:02:28

2023-02-26 23:43:43

MySQL數(shù)據(jù)庫分頁查詢

2010-05-25 15:12:22

MySQL分頁

2021-02-11 13:30:56

Nodejs源碼c++

2010-05-17 17:23:27

MySQL limit

2010-11-25 10:12:02

MySQL查詢優(yōu)化

2022-02-09 07:44:30

Go源碼工具

2022-01-26 07:18:57

工具GoGo 項目

2012-09-06 10:07:26

jQuery

2021-01-04 05:53:35

MyBatis底層Java

2011-03-09 13:06:29

LimitMySQL
點贊
收藏

51CTO技術(shù)棧公眾號

欧美欧美全黄| 久草在线资源站手机版| 蜜臀久久久久久久| 欧美成人激情视频| 亚洲中文字幕无码一区| 毛片无码国产| 亚洲人成网站色在线观看| 国产精品传媒毛片三区| 中文字幕在线播| 久久一区二区三区电影| 精品国产乱码久久久久久久| 国产成人久久婷婷精品流白浆| 91大神xh98hx在线播放| 成人免费毛片aaaaa**| 国产精品福利在线观看网址| 欧美国产日韩综合| 欧美日韩色图| 亚洲成人av资源网| 欧美激情第3页| 日韩av影片| 一区二区三区视频在线观看| 欧美精品一区二区三区四区五区| 国产片高清在线观看| 久久人人97超碰国产公开结果| 麻豆国产va免费精品高清在线| 91中文字幕永久在线| 在线观看视频一区二区三区| 欧美三级午夜理伦三级中视频| 777av视频| 最新国产在线拍揄自揄视频| 日本一区二区三区在线不卡| 久久伊人资源站| 精品久久久久成人码免费动漫| 美女视频一区二区| 日本中文字幕久久看| 国产午夜精品一区二区理论影院| 希岛爱理av一区二区三区| 亚洲视频精品在线| 欧美性xxxx图片| 黄色成人美女网站| 精品久久久久久最新网址| 中文字幕色网站| 视频欧美精品| 欧美伦理视频网站| 色婷婷综合网站| 777午夜精品电影免费看| 一本久道久久综合中文字幕| 无码人妻丰满熟妇区96| 国产在线美女| 精品久久久精品| 免费观看美女裸体网站| 成人免费观看在线观看| 亚洲1区2区3区视频| 久久这里只有精品18| 天堂av最新在线| 一区二区三区欧美久久| 日本福利视频在线观看| 丝袜综合欧美| 亚洲成av人片在www色猫咪| www.av毛片| 偷拍自拍在线看| 日韩欧美一区二区三区久久| 日韩欧美xxxx| 97精品国产99久久久久久免费| 欧美在线不卡一区| gogogo高清免费观看在线视频| 亚洲精品无播放器在线播放| 欧美一区二区免费| 中文字幕精品视频在线| 神马午夜久久| 在线观看中文字幕亚洲| 蜜桃av.com| 欧美日韩伊人| 8x海外华人永久免费日韩内陆视频| 日韩经典在线观看| 日韩中文字幕亚洲一区二区va在线 | 国产a级黄色片| 在线看成人短视频| 色av中文字幕一区| 久草资源在线视频| 久久精品人人| 成人久久久久久| 人妻精品一区一区三区蜜桃91| 99久久99久久精品免费看蜜桃| 欧美13一14另类| 麻豆视频在线观看免费网站| 亚洲一二三区在线观看| 能看的毛片网站| 国产日韩一区二区三免费高清 | 九色在线视频| 亚洲视频免费在线| 国模无码视频一区二区三区| 国产亚洲欧美日韩精品一区二区三区 | 9l视频白拍9色9l视频| 久久久久久亚洲精品美女| 亚洲国产精品成人va在线观看| 中国女人特级毛片| 亚洲无线视频| 国产精品一区二区三区毛片淫片 | 国产性生活视频| 黑人精品欧美一区二区蜜桃| 精品国产乱码久久久久久丨区2区 精品国产乱码久久久久久蜜柚 | 捆绑变态av一区二区三区| 成人毛片网站| 日本中文字幕伦在线观看| 午夜激情久久久| 五月天婷婷在线观看视频| 日本韩国欧美超级黄在线观看| 中文字幕在线精品| 亚洲天堂日韩av| 国产一区二区精品久久91| 美日韩精品免费| 免费在线观看的电影网站| 欧美在线视频全部完| 中文字幕天堂av| 亚洲精品国产首次亮相| 国产成人精品电影| 深夜福利视频网站| 亚洲丝袜另类动漫二区| 不卡av免费在线| 久久久久观看| 美日韩精品免费视频| 波多野结衣电车| 91丨porny丨首页| 免费在线看黄色片| 久久伊人久久| 久久综合伊人77777蜜臀| 欧美 亚洲 另类 激情 另类| 91性感美女视频| 成人免费在线网| 警花av一区二区三区| 丝袜一区二区三区| 波多野结衣视频在线看| 91蜜桃视频在线| 欧美日韩精品在线一区二区| 一区二区免费| 欧美国产日韩免费| 亚洲精品综合网| 亚洲午夜久久久久久久久久久| 国产免费中文字幕| 999国产精品999久久久久久| 国产精品日韩欧美大师| 黄色av免费在线观看| 一本大道av一区二区在线播放| 国产日韩视频一区| 影音先锋久久资源网| 国产精品一码二码三码在线| 麻豆av在线播放| 精品99999| 日韩美女黄色片| av一二三不卡影片| 日本www在线播放| 亚洲品质自拍| 国产精品久久久精品| 成人免费高清在线播放| 欧美四级电影网| 手机免费观看av| 国产一区二区三区四区五区美女| 国产精品亚洲天堂| 亚洲天堂av资源在线观看| 欧美日本国产在线| 天堂在线视频网站| 在线亚洲一区二区| 国产麻豆a毛片| 国产999精品久久| 日韩精品 欧美| 国内精品伊人久久久| 国产色综合天天综合网| 在线观看男女av免费网址| 亚洲精品一区二区三区在线观看| 日韩精品久久久久久久酒店| 久久久久久久久久久久久久久99| 五月婷婷狠狠操| 亚洲成av人电影| 国产一区二区三区高清视频| 亚洲成人人体| 久久综合久久美利坚合众国| 少妇人妻偷人精品一区二区| 欧美亚洲综合一区| 极品颜值美女露脸啪啪| 91在线你懂得| 午夜精品免费看| 亚洲区第一页| 神马影院午夜我不卡| 久久九九精品视频| 国产成人精品久久二区二区| 呦呦在线视频| 国产午夜精品视频| 成人午夜福利视频| 在线观看av一区二区| 青青草国产在线观看| 国产亚洲一区字幕| 26uuu国产| 日本最新不卡在线| 久青草视频在线播放| 欧美一区二区三区激情视频| 不卡一区二区三区视频| 日韩三区免费| 韩国三级日本三级少妇99| seseavlu视频在线| 亚洲成年人在线| 一区二区国产欧美| 精品国产电影一区| 欧美精品成人久久| 国产精品美女久久久久久久| 性久久久久久久久久久| 国产美女精品在线| 免费一级特黄录像| 亚洲欧美日本国产专区一区| 97超碰免费观看| sdde在线播放一区二区| 精品一区二区久久久久久久网站| 精品麻豆剧传媒av国产九九九| 国产成人精品日本亚洲| rebdb初裸写真在线观看| 久久最新资源网| av天在线观看| 亚洲午夜精品久久久久久性色| 丁香花免费高清完整在线播放| 欧美三级中文字| 无码人妻精品一区二区三区不卡 | 成人免费在线视频观看| 中文字幕国产专区| 91尤物视频在线观看| 日本wwwxx| 国产精品综合视频| 三区视频在线观看| 美女一区二区久久| 亚洲36d大奶网| 日韩极品在线观看| 男人透女人免费视频| 国产日韩欧美在线播放不卡| 日韩精品在线观看av| 欧美精品三区| 99亚洲国产精品| 1024精品久久久久久久久| 亚洲精品日韩成人| 色喇叭免费久久综合| 日韩精品一区二区三区四区五区| 在线亚洲a色| 欧美在线激情| 欧美中文字幕一区二区| 日本一区二区三区视频免费看| 深爱激情久久| 亚欧精品在线| 日韩欧美午夜| 日韩人妻精品一区二区三区| 在线电影一区二区| 欧美激情亚洲天堂| 99精品国产在热久久下载| 日本精品一区在线观看| 欧美中文日韩| 天天爽天天爽夜夜爽| 麻豆成人免费电影| 中文字幕在线视频精品| 国产成人精品www牛牛影视| 亚洲欧洲国产视频| 91亚洲精品一区二区乱码| 极品粉嫩小仙女高潮喷水久久 | 欧美精品一区二区精品网| 天天操天天射天天| 亚洲欧洲一区二区三区久久| 成年人在线观看| 大胆欧美人体视频| 3344国产永久在线观看视频| 5566成人精品视频免费| 一二区成人影院电影网| 成人在线视频福利| 伊人久久亚洲| 欧美日韩在线精品| 久久久国产精品| 成 年 人 黄 色 大 片大 全| 亚洲欧美成人综合| 亚洲第一天堂久久| av不卡在线观看| a级黄色免费视频| 夜夜嗨av一区二区三区网页 | 亚洲一二三四五六区| 樱桃国产成人精品视频| 黄色大片网站在线观看| 欧美三级中文字幕| 天天干天天干天天干| 一区二区欧美日韩视频| 亚洲精品中文字幕无码蜜桃| 91av亚洲| 国产精品美女久久久免费| 国产精品视频一区二区三区| 国产精品高清一区二区三区| 亚洲人成精品久久久| 中国老女人av| 亚洲一区成人| 九九九九九九九九| 91日韩在线专区| 91视频8mav| 一区二区中文字幕在线观看| 农村寡妇一区二区三区| 亚洲情侣在线| 亚洲自偷自拍熟女另类| 久草在线在线精品观看| 特大黑人巨人吊xxxx| ㊣最新国产の精品bt伙计久久| 日韩视频免费观看高清| 欧美精品aⅴ在线视频| 三级av在线播放| 欧美国产日韩在线| 成人国产激情| 久久久人人爽| 欧美色123| 中文字幕国产高清| 国产丝袜美腿一区二区三区| 高清毛片在线看| 超碰97人人做人人爱少妇| 亚洲欧洲日本韩国| av免费精品一区二区三区| 国产精品一区二区av交换| 97中文字幕在线| 韩日精品视频一区| 欧美xxxx精品| 在线精品视频免费观看| 四虎在线观看| 久久久久久久久久久免费| 久久久久久久国产视频| 色综合欧美在线| 欧美一区二区三区黄片| 美女福利视频一区| 久久亚洲国产精品尤物| 日本一区二区久久精品| 日韩视频一区二区三区在线播放免费观看| 亚洲黄色av片| 中文字幕一区二区三区四区| 国产成人自拍偷拍| 亚洲女成人图区| 一区二区三区短视频| 好吊色欧美一区二区三区| 亚洲网站在线| 无码国产69精品久久久久网站| 一卡二卡三卡日韩欧美| 99久久精品国产成人一区二区| www.欧美三级电影.com| 日韩欧国产精品一区综合无码| 四虎影视永久免费在线观看一区二区三区| 国产亚洲毛片在线| 亚洲黄色在线网站| 日韩欧美亚洲综合| 极品白浆推特女神在线观看 | 日本高清不卡一区二区三| 国产日韩综合| 免费看污片网站| 在线观看区一区二| 五月婷婷在线视频| 成人激情在线播放| 欧美精品综合| 91精品又粗又猛又爽| 欧美日韩国产在线| 青青操视频在线| 国产精品久久婷婷六月丁香| 日韩综合一区| 日本亚洲一区二区三区| 一区二区成人在线| 三级在线电影| 国产精品白丝jk喷水视频一区 | 日韩中文字幕不卡视频| 国产亚洲精品精品国产亚洲综合| 综合视频在线观看| 大白屁股一区二区视频| 日韩黄色精品视频| 一区三区二区视频| 精品视频91| 日本www在线视频| 欧美国产精品v| 国产成人精品毛片| 91av国产在线| 色综合天天综合网中文字幕| 日本少妇一区二区三区| 精品国产乱码久久久久久婷婷| 国产女人在线观看| 亚洲xxx视频| 亚洲资源av| 国产大片免费看| 日韩精品一区二区三区第95| 成人做爰免费视频免费看| 喜爱夜蒲2在线| 久久蜜臀中文字幕| 国产视频一二三四区| 97超级碰碰碰久久久| 久久国产小视频| 免费日本黄色网址| 欧美人伦禁忌dvd放荡欲情| 久久亚洲导航| 精品播放一区二区| 精品自拍偷拍视频| 精品免费视频一区二区| 欧美xxxxxx| 成人小视频在线观看免费| 国产日产欧美一区二区视频| 精品人妻无码一区二区 | 免费在线成人激情电影| 蜜桃视频一区二区在线观看| 国产亚洲欧美色| 日本高清视频免费观看|