精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

亚洲成人黄色av| 9久久9毛片又大又硬又粗| 一卡二卡在线观看| 伊人久久亚洲热| 亚洲人成网站999久久久综合| 中文av一区二区三区| 先锋影音在线资源站91| 久久综合99re88久久爱| 国产精品网红直播| 精品在线免费观看视频| 国产一区二区三区四区二区| 欧美精品aⅴ在线视频| 少妇高潮喷水在线观看| 麻豆最新免费在线视频| 99久久婷婷国产综合精品| 国产精品一区久久久| 日本系列第一页| 欧美电影一区| 亚洲美女福利视频网站| 亚洲国产日韩在线一区| 97欧美成人| 亚洲18色成人| 天天做天天爱天天高潮| 国产在线电影| 成人h精品动漫一区二区三区| 国产裸体写真av一区二区| 天天综合天天干| 狠狠综合久久| 久久艳片www.17c.com| 舐め犯し波多野结衣在线观看| 91亚洲精品视频在线观看| 欧美精品日韩一区| 美女一区二区三区视频| 91精品论坛| 天天综合天天做天天综合| 三上悠亚免费在线观看| 色的视频在线免费看| 久久先锋资源网| 国产乱码精品一区二区三区中文| 亚洲中文一区二区三区| 日韩中文欧美在线| 日本精品久久久久影院| www日韩精品| 亚洲国产日本| 韩剧1988在线观看免费完整版 | 国产视频不卡一区| 久久久久久久久久久久久久一区 | 26uuu国产| 91成人小视频| 91久久国产综合久久| 99色精品视频| 欧美日韩免费看片| 欧美午夜无遮挡| 99re在线视频免费观看| 女人让男人操自己视频在线观看 | 又粗又黑又大的吊av| av电影免费在线看| 婷婷综合久久一区二区三区| 成 年 人 黄 色 大 片大 全| 九色porny丨入口在线| 午夜精品一区二区三区电影天堂| 丁香花在线影院观看在线播放| 羞羞的网站在线观看| 一区二区三区在线观看动漫| 国产女教师bbwbbwbbw| 欧美xxxx性xxxxx高清| 亚洲午夜精品在线| 久久福利网址导航| 娇妻被老王脔到高潮失禁视频| 啪啪亚洲精品| 中文字幕亚洲欧美日韩高清| 青青操在线视频观看| 伊人色**天天综合婷婷| 欧美日韩成人网| 五月天综合激情| 日本欧美一区二区三区| 国产主播在线一区| 亚洲成人一二三区| 99这里只有精品| 日韩国产美国| 26uuu亚洲电影在线观看| 亚洲自拍偷拍欧美| 91好吊色国产欧美日韩在线| 日韩福利一区| 欧美一区二区三区影视| 97精品人妻一区二区三区蜜桃| 欧美日韩看看2015永久免费 | 黑人精品视频| 日韩欧美在线视频免费观看| 一区二区三区 日韩| 午夜日韩影院| 亚洲欧美激情精品一区二区| 亚洲女人久久久| 日韩视频在线一区二区三区 | 亚洲视频精选在线| 妺妺窝人体色777777| 天堂中文av在线资源库| 欧美色图第一页| 日本成人在线免费| 激情五月色综合国产精品| 久久亚洲精品一区| 青青草免费观看视频| 韩国欧美国产1区| 国产一区在线免费观看| 欧洲美女少妇精品| 精品免费在线视频| 91视频免费入口| 成人毛片免费看| 韩国欧美亚洲国产| 亚洲一区中文字幕永久在线| 91啦中文在线观看| 日韩亚洲欧美一区二区| а√天堂资源国产精品| 精品av久久707| 91狠狠综合久久久| 久久婷婷丁香| 精品视频一区在线| 性欧美videos高清hd4k| 在线免费观看不卡av| 日韩精品人妻中文字幕有码| 国产精品成人a在线观看| 国产mv免费观看入口亚洲| 成人激情四射网| **欧美大码日韩| 污污视频网站免费观看| 国产精品对白久久久久粗| 久久久99久久精品女同性| 人人妻人人爽人人澡人人精品| 波多野结衣91| 国内少妇毛片视频| 午夜视频一区二区在线观看| 在线观看国产成人av片| 日韩中文字幕高清| 久久在线观看免费| 国产综合av在线| 精品福利网址导航| 久久久久久亚洲精品| av天堂一区二区三区| 中文字幕在线观看一区| 午夜免费高清视频| 欧美男gay| 欧美亚洲日本黄色| 天堂中文资源在线| 偷拍亚洲欧洲综合| 野外性满足hd| 亚洲免费在线| 欧美日韩亚洲综合一区二区三区激情在线| 波多野结衣中文字幕久久| 欧美一区二区三区四区视频| 国产精品国产三级国产传播| 老司机一区二区| 26uuu成人| 日韩精品视频中文字幕| 九九热这里只有精品6| 精品人妻无码一区二区色欲产成人 | 日韩片电影在线免费观看| 日韩高清中文字幕一区二区| 亚洲欧美精品一区| 国产精品自拍第一页| 亚洲国产精品精华液2区45| av五月天在线| 91精品国产91久久久久久密臀| 成人精品一区二区三区| a级网站在线播放| 精品美女一区二区| 国产手机在线视频| 国产午夜一区二区三区| 亚洲一级免费在线观看| 亚洲精品a级片| 国产精品露出视频| 亚洲淫成人影院| 中文字幕视频在线免费欧美日韩综合在线看 | 久久久久久久久久久久久9999| 香蕉久久免费电影| zzijzzij亚洲日本成熟少妇| www.热久久| 日韩欧美极品在线观看| 秋霞网一区二区三区| 国产一区二区三区免费| 国产69精品久久久久999小说| 免费久久精品| 亚洲xxxxx电影| 色网在线免费观看| 日韩中文字幕免费看| 精品国产av一区二区三区| 欧美日韩精品在线播放| 亚洲黄色网址大全| 丁香激情综合国产| 妓院一钑片免看黄大片| 亚洲五月综合| 蜜桃麻豆www久久国产精品| 亚洲高清国产拍精品26u| 欧美第一黄网免费网站| 国产三级在线免费| 精品久久久久久久人人人人传媒 | 久久国产精品无码网站| 国产黄色激情视频| 精品精品久久| 国产欧美日韩一区二区三区| 69堂免费精品视频在线播放| 久久久久久久久久久91| 日本在线免费| 精品五月天久久| 精品人妻一区二区三区麻豆91| 欧美性生交大片免网| 日韩一级片大全| 国产亚洲自拍一区| 国产精品成人无码专区| 精品一区二区影视| 18岁视频在线观看| 亚洲二区在线| 永久免费网站视频在线观看| 国产探花一区| 九九九热999| 91免费精品国偷自产在线在线| 国产欧美日韩视频| 综合在线影院| 午夜精品久久久久久久99热| huan性巨大欧美| 色诱女教师一区二区三区| 日韩毛片在线一区二区毛片| 日韩精品专区在线影院重磅| 在线观看xxxx| 欧美亚洲国产怡红院影院| 天天操天天爽天天干| 亚洲午夜激情网页| 久热这里有精品| 中文字幕欧美一| 国产成人在线网址| 国产女同性恋一区二区| 国产精品揄拍100视频| 99免费精品在线| 国产免费a级片| 国产精品1区2区3区在线观看| 天天综合网久久| 美女一区二区三区在线观看| 老头吃奶性行交视频| 久久精品官网| 免费av网址在线| 欧美一区=区| 北条麻妃在线观看| 久久久夜夜夜| 无码无遮挡又大又爽又黄的视频| 亚洲自啪免费| 黄色高清无遮挡| 丝瓜av网站精品一区二区| av片中文字幕| 日本亚洲天堂网| 奇米影视四色在线| 精品一区精品二区高清| 亚洲三级在线观看视频| 国产精品一区三区| 丰满人妻一区二区三区大胸| 成人福利视频在线| 精品人妻一区二区三区日产乱码卜| fc2成人免费人成在线观看播放| 欧美xxxx×黑人性爽| 26uuu色噜噜精品一区二区| 99久久人妻精品免费二区| 久久综合五月天婷婷伊人| 久久精品国产亚洲AV熟女| 欧美激情中文字幕一区二区| 美女福利视频网| 亚洲黄一区二区三区| 国产精品18p| 色婷婷av久久久久久久| 国产91av在线播放| 777奇米成人网| 亚洲国产一二三区| 亚洲区一区二区| 五月婷婷在线视频| 久久九九亚洲综合| 超碰在线中文字幕| 日本国产高清不卡| 日韩av黄色| 国产精品久久亚洲7777| 国产尤物久久久| 黄色录像特级片| 久久www成人_看片免费不卡| 依人在线免费视频| 成人午夜视频免费看| 亚洲黄色在线网站| 中文字幕亚洲电影| 国产成人亚洲欧洲在线| 欧美日韩午夜在线| 亚洲av综合色区无码一二三区 | 水野朝阳av一区二区三区| www.国产福利| 久久综合久久综合久久综合| 国产wwwwxxxx| 亚洲一区二区视频在线| 无码人妻一区二区三区免费| 在线不卡中文字幕播放| 亚洲av成人无码久久精品老人| 深夜福利一区二区| 天堂av在线| 91在线观看免费高清| 一区二区三区视频免费视频观看网站| 欧美另类一区| 欧美激情综合色综合啪啪| 可以免费在线看黄的网站| 国产精品一区二区在线播放 | 你懂的网址国产 欧美| 成人免费无码av| 成人国产精品免费观看动漫| 日本黄色激情视频| 欧美日韩国产限制| 精品乱子伦一区二区| 综合国产在线观看| 日本在线影院| 国产精品sss| 91精品国偷自产在线电影 | 激情欧美一区二区三区黑长吊| 久久国产精品-国产精品| 亚洲理论电影网| 欧美精品性生活| 久久日一线二线三线suv| 精品少妇久久久| 制服丝袜亚洲精品中文字幕| 国产高清一级毛片在线不卡| 91av视频在线播放| 国产成人精品亚洲线观看| 久久精品在线免费视频| 久久精品久久精品| 91成人精品一区二区| 欧美日韩一区二区在线| 欧美一级免费片| 久久99精品久久久久久青青91| 色噜噜成人av在线| 亚欧精品在线| 日本中文在线一区| 亚洲区自拍偷拍| 色老头久久综合| 精彩国产在线| 国产成人av在线播放| 亚洲精品aaaaa| 国产精品免费观看久久| 99这里只有精品| 亚洲男人的天堂在线视频| 亚洲精品久久久久久久久久久久 | 国产精品扒开腿做爽爽爽的视频| 啪啪国产精品| 91精品91久久久中77777老牛| 91在线一区二区三区| 国产污污视频在线观看| 亚洲精品999| 在线亚洲人成| 日韩一区二区三区高清| 青娱乐精品视频| 长河落日免费高清观看| 欧美日韩国产一区二区三区地区| 三区四区在线视频| 亚洲iv一区二区三区| 欧美精品午夜| 美女又爽又黄免费| 色婷婷精品大在线视频| а天堂8中文最新版在线官网| 国产精品视频网址| 偷拍欧美精品| 性生交大片免费看l| 激情成人中文字幕| 免费国产在线视频| 国产精品网址在线| 亚洲最大黄网| 亚洲男人在线天堂| 在线视频国产一区| 韩国中文字幕在线| 国产视频一区二区不卡| 久久久久久夜| 97在线观看免费高| 亚洲国产福利在线| 色综合一本到久久亚洲91| 99re99热| av高清久久久| 中文天堂在线资源| 欧美另类在线播放| 亚洲欧美成人vr| 中文字幕永久有效| 午夜激情一区二区| www.黄在线观看| 成人久久18免费网站漫画| 亚洲影院一区| 暗呦丨小u女国产精品| 亚洲精品福利视频| 91精品福利观看| 成人性免费视频| 国产精品超碰97尤物18| 色欲av永久无码精品无码蜜桃| 国产精欧美一区二区三区| 欧美激情麻豆| 黄色片网站免费| 日韩你懂的在线观看| 一二区成人影院电影网| av在线免费观看国产| 欧美经典三级视频一区二区三区| 精品国产九九九| 国产精品xxx视频| 亚洲青涩在线| 日韩国产第一页| 亚洲欧洲在线观看|