目錄
- 一條語句的函數調用棧順序
- 8.0使用迭代器模式改進executor
- int *handler*::ha_rnd_next(*uchar* **buf*)
- int *TableScanIterator*::Read()
- int FilterIterator :: Read()
- int HashJoinIterator::Read()
- int NestedLoopIterator :: Read()
- int StreamingIterator::Read ()
- *ha_rows* read_all_rows
- 回顧迭代器模式
一條語句的函數調用棧順序
記錄了函數語句從服務器main函數到執行器之前的一些具體調用,5.幾版本到8.0.22版本,這里的調用順序并沒有多大變化
注意這里是接著上面的2、
處理完之后,開始返回,返回到之前的case
按照網上代碼版本接下來的調用順序應該是這樣的:這里的JOIN::exec()
和do_select
我沒有在8.0代碼中找到,就直接跳過這兩個函數吧。
8.0使用迭代器模式改進executor
在文章https://cloud.tencent.com/developer/article/1461353中說道:
MySQL8.0對執行器進行了改進,創建一個新的用于迭代訪問記錄的API,它足夠通用,可以替換MySQL中所有原有的記錄迭代器,并逐步替代掉原有的執行器。
這是之前的執行器接口:
這是現在的:
該文章列出了一些迭代器類型:
TableScanIterator:順序掃描,調用存儲引擎接口ha_rnd_next獲取一行記錄。
IndexScanIterator:全量索引掃描,根據掃描順序,分別調用ha_index_next或者ha_index_prev來獲取一行記錄。
IndexRangeScanIterator:范圍索引掃描,包裝了下QUICK_SELECT_I,調用QUICK_SELECT_I::get_next來獲取一行記錄。
SortingIterator:對另一個迭代器輸出進行排序。
SortBufferIterator:從緩沖區讀取已經排好序的結果集,(主要給SortingIterator調用)
SortBufferIndirectIterator:從緩沖區讀取行ID然后從表中讀取對應的行(由SortingIterator和某些形式的unique操作使用)
SortFileIterator:從文件中讀取已經排好序的結果集(主要給SortingIterator調用)
SortFileIndirectIterator:從文件讀取行ID然后從表中讀取對應的行(由SortingIterator和某些形式的unique操作使用)
RefIterator:從連接右表中讀取指定key的行。
RefOrNullIterator:從連接右表中讀取指定key或者為NULL的行。
EQRefIterator:使用唯一key來從連接的右表中讀取行。
ConstIterator:從一個只可能匹配出一行的表(Const Table)中讀取一行數據。
FullTextSearchIterator:使用全文檢索索引讀取一行數據。
DynamicRangeIterator:為每一行調用范圍優化器,然后根據需要包裝QUICK_SELECT_I或表掃描。
PushedJoinRefIterator:讀取已下推到NDB的連接的輸出。
FilterIterator: 讀取一系列行,輸出符合條件的行,用來實現WHERE/HAVING。
LimitOffsetIterator: 從offset開始讀取行,直到滿足limit限制,用來實現LIMIT/OFFSET。
AggregateIterator: 實現聚集函數并且如果需要的話進行分組操作。
NestedLoopiterator: 使用嵌套循環算法連接兩個迭代器(內連接,外連接或反連接)。
MaterializeIterator: 從另一個迭代器讀取結果,并放入臨時表,然后讀取臨時表記錄。
FakeSingleRowIterator: 返回單行,然后結束。 僅在某些使用const表情況下才使用(例如只有const表,仍然需要一個迭代器來讀取該單行)
下面是我對mysql語句
use table;
debug時發現的迭代器調用順序:
不知道解讀是否正確。
之后就是將結果排序:
int handler::ha_rnd_next(uchar *buf)
https://dev.mysql.com/doc/dev/mysql-server/latest/classhandler.html#ad3743f3a48e7be751dbb2691be4c992a
int TableScanIterator::Read()
https://dev.mysql.com/doc/dev/mysql-server/latest/classFilterIterator.html
int FilterIterator :: Read()
一個迭代器,它接收一行流,并且僅通過那些滿足某些條件(即條件的結果為true)的行。
https://dev.mysql.com/doc/dev/mysql-server/latest/classFilterIterator.html#a166014f053203bb025d12e95180d8ffa
int HashJoinIterator::Read()
https://dev.mysql.com/doc/dev/mysql-server/latest/classHashJoinIterator.html#a64f8107d4a8b3bb1ab7804e9e1c2689c
int NestedLoopIterator :: Read()
一個簡單的嵌套循環連接,接受兩個迭代器(左/外和右/內)并將他們連接到一起。這可能會多次掃描內部迭代器。迭代器用作狀態機,其中狀態記錄我們是否需要讀取新的外部行,以及是否從內部迭代器中看到任何行(如果沒有,則外部聯接需要合成新的行)
https://dev.mysql.com/doc/dev/mysql-server/latest/classNestedLoopIterator.html
int StreamingIterator::Read ()
https://dev.mysql.com/doc/dev/mysql-server/latest/classStreamingIterator.html#details
StreamingIterator的每個Read()只會將調用轉給子查詢迭代器,并執行從一組字段到另一組的所需復制。它用于優化程序設置的實現的時間。
It is used for when the optimizer would normally set up a materialization, but you don't actually need one, ie. you don't want to read the rows multiple times after writing them, and you don't want to access them by index (only a single table scan). It also takes care of setting the NULL row flag on the temporary table.
這段英文沒讀懂。。。
ha_rows read_all_rows
讀取所有行,并將它們寫入一個臨時文件(如果我們在排序緩沖區中空間不足)。
保證所有產生的序列都是非空的。返回的是成功記錄的記錄數
https://dev.mysql.com/doc/dev/mysql-server/latest/filesort_8cc.html#acfc65b7a8828ea94df20c3944d1947fd
回顧迭代器模式
迭代器模式:提供一種方法順序訪問一個聚合對象中各個元素,而不暴露該對象的內部表示。
當我們需要訪問一個聚集對象,而且不管這些對象是什么都需要遍歷的時候,就應該考慮用迭代器模式。
(針對不同對象)
當我們對聚集有多種方式遍歷時,可以考慮用迭代器模式。(針對不同遍歷方式,如從前往后、從后往前)
為遍歷不同的聚集結構提供統一接口。
關于MySQL8.0版本的迭代器的作用在后面的筆記繼續介紹。