MySQL 8.0.22執行器源碼分析HashJoin —— BuildHashTable函數細節步驟

BuildHashTable函數細節步驟

該函數位置處于hash_join_iterator.cc 403 ~ 560行

step1:如果被驅動表迭代器沒有更多的行數,更新m_state為EOR,然后返回false,表明創建hash表失敗

if (!m_build_iterator_has_more_rows) {m_state = State::END_OF_ROWS;return false;
}

**step2:**還原插入行緩沖區的最后一行。如果構建輸入是一個嵌套循環,內部有一個過濾器,那么這是必需的。這里還不是很理解

if (m_row_buffer.Initialized() &&m_row_buffer.LastRowStored() != m_row_buffer.end()) {hash_join_buffer::LoadIntoTableBuffers(m_build_input_tables, m_row_buffer.LastRowStored()->second);
}

step3:清除行buffer并且將多有迭代器重新指向它。如果初始化成功,直接返回true。

if (InitRowBuffer()) {return true;
}

step4:初始化了兩個變量

reject_duplicate_keysstore_rows_with_null_in_join_key

const bool reject_duplicate_keys = RejectDuplicateKeys();
const bool store_rows_with_null_in_join_key = m_join_type == JoinType::OUTER;

RejectDuplicateKeys()函數返回值為true的話,說明拒絕哈希表中的重復鍵。當遇到半連接或反連接等相同鍵值只需要返回一條結果,不需要返回extra情況。

對于反連接與半連接可以參考:半連接&反連接

指明當前jointype為外連接JoinType::OUTER

step5:將被驅動表輸入的SetNullRowFlag清除。這是為了防止hashjoin用于獨立子查詢時init被調用多次的情況,不然這個標志將被之前執行的hashjoin操作污染。

m_build_input->SetNullRowFlag(/*is_null_row=*/false);

step6:開始通過迭代器從m_build_input循環讀數據,

1、如果線程被kill的話,返回true。

2、當build input為空,內連接和半連接結果也會為空,然而反連接的輸出將是probe input的所有行

3、當讀到build 迭代器的最后一行,這說明我們不會再去在probe 迭代器中讀取數據了。這時候需要我們禁止probe row保存數據

PFSBatchMode batch_mode(m_build_input.get());
for (;;) {  // Termination condition within loop.int res = m_build_input->Read();if (res == 1) {DBUG_ASSERT(thd()->is_error() ||thd()->killed);  // my_error should have been called.return true;}if (res == -1) {m_build_iterator_has_more_rows = false;// If the build input was empty, the result of inner joins and semijoins// will also be empty. However, if the build input was empty, the output// of antijoins will be all the rows from the probe input.if (m_row_buffer.empty() && m_join_type != JoinType::ANTI &&m_join_type != JoinType::OUTER) {m_state = State::END_OF_ROWS;return false;}// As we managed to read to the end of the build iterator, this is the// last time we will read from the probe iterator. Thus, we can disable// probe row saving again (it was enabled if the hash table ran out of// memory _and_ we were not allowed to spill to disk).m_write_to_probe_row_saving = false;SetReadingProbeRowState();return false;}

step7

1、請求所有表的行ID

2、存儲當前位于表記錄緩沖區中的行,將其放到store_row_result中

3、根據store_row_result狀態進行處理

  • 如果是*ROW_STORED*,說明已經存儲完畢,直接break

     case hash_join_buffer::StoreRowResult::ROW_STORED:break;
    
  • 如果是BUFFER_FULL,說明緩存區已經滿了.

    如果允許的話,向磁盤操作。如果不允許向磁盤操作,就繼續從probe 迭代器中讀取數據,并且開啟probe row保存,這樣沒有匹配的probe rows將被寫到saving file中。在下一次refill hash表的時候,從saving file中讀取probe row。

    if (!m_allow_spill_to_disk) {if (m_join_type != JoinType::INNER) {// Enable probe row saving, so that unmatched probe rows are written// to the probe row saving file. After the next refill of the hash// table, we will read rows from the probe row saving file, ensuring// that we only read unmatched probe rows.InitWritingToProbeRowSavingFile();}SetReadingProbeRowState();return false;
    }
    // If we are not allowed to spill to disk, just go on to reading from// the probe iterator.
    if (!m_allow_spill_to_disk) {if (m_join_type != JoinType::INNER) {// Enable probe row saving, so that unmatched probe rows are written// to the probe row saving file. After the next refill of the hash// table, we will read rows from the probe row saving file, ensuring// that we only read unmatched probe rows.InitWritingToProbeRowSavingFile();}SetReadingProbeRowState();return false;
    }
    

    初始化兩個input的hashjoinchunk。估計需要多少chunks,planner會事先給出一個數,這里會重新計算得到每個塊都合適的磁盤塊。

    if (InitializeChunkFiles(m_estimated_build_rows, m_row_buffer.size(), kMaxChunks,m_probe_input_tables, m_build_input_tables,/*include_match_flag_for_probe=*/m_join_type == JoinType::OUTER,&m_chunk_files_on_disk)) {DBUG_ASSERT(thd()->is_error());  // my_error should have been called.return true;
    }
    

    將迭代器上剩余的數據寫到磁盤的chunk file上,如果出現IO錯誤的話,返回true

    if (WriteRowsToChunks(thd(), m_build_input.get(), m_build_input_tables,m_join_conditions, kChunkPartitioningHashSeed,&m_chunk_files_on_disk,true /* write_to_build_chunks */,false /* write_rows_with_null_in_join_key */,m_tables_to_get_rowid_for,&m_temporary_row_and_join_key_buffer)) {DBUG_ASSERT(thd()->is_error() ||thd()->killed);  // my_error should have been called.return true;
    }
    

    從build input起始地方刷新并定位所有chunk files。

    for (ChunkPair &chunk_pair : m_chunk_files_on_disk) {if (chunk_pair.build_chunk.Rewind()) {DBUG_ASSERT(thd()->is_error() ||thd()->killed);  // my_error should have been called.return true;}
    }
    SetReadingProbeRowState();
    return false;
    }
    
  • 如果狀態為FATAL_ERROR,說明出現意料之外的錯誤,可能是malloc失敗。返回true。

case hash_join_buffer::StoreRowResult::FATAL_ERROR:// An unrecoverable error. Most likely, malloc failed, so report OOM.// Note that we cannot say for sure how much memory we tried to allocate// when failing, so just report 'join_buffer_size' as the amount of// memory we tried to allocate.my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),thd()->variables.join_buff_size);return true;}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377031.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377031.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377031.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《那些年啊,那些事——一個程序員的奮斗史》——125

距離離職交接的一個月時間還剩幾天,本來應該是平淡無事的,卻沒想到最后還是波瀾四起。昨天下班前,公司突然停了電。這本是件普通得不能再普通的事情,可沒想到過了一會來電了,或許是波峰電壓太大,或許是穩壓…

python中的元類_Python中的元類

python中的元類Python元類 (Python metaclass) A metaclass is the class of a class. A class defines how an instance of a class i.e.; an object behaves whilst a metaclass defines how a class behaves. A class is an instance of a metaclass. 元類是類的類。 一個類…

MySQL 8.0.22執行器源碼分析HashJoin —— 一些初始化函數的細節步驟

目錄InitRowBuffer(101行~126行)InitProbeIterator(142行~153行)*HashJoinIterator* 的Init(155行~240行)InitializeChunkFiles(364行~401行)InitWritingToProbeRowSavingFile&#…

c語言的宏定義學習筆記

宏定義 在預處理之前,c預處理器會對代碼進行翻譯,譬如用blank替換注釋,去掉多余的空格,刪除末尾的\來拼接行等。 例如: int /*注釋*/ x; 會被翻譯成 int x; printf("this is a s\ entence."); 會被翻譯成 pr…

攝氏溫度轉換華氏溫度_什么是攝氏溫度?

攝氏溫度轉換華氏溫度攝氏溫度 (Celsius) Celsius is a temperature measuring scale which as a SI unit derived from the seven base units stated and described by the International System of Units (SI). 攝氏溫度是一種溫度測量刻度,它是由國際單位制(SI)所…

別人的算法學習之路

http://www.cnblogs.com/figure9/p/3708351.html 我的算法學習之路 關于 嚴格來說,本文題目應該是我的數據結構和算法學習之路,但這個寫法實在太繞口——況且CS中的算法往往暗指數據結構和算法(例如算法導論指的實際上是數據結構和算法導論&a…

git config命令使用第二篇——section操作,多個key值操作,使用正則

接上一篇,git config命令使用第一篇——介紹,基本操作,增刪改查:http://blog.csdn.net/hutaoer06051/article/details/8275069 1. 刪除一個section 命令參數 --remove-section 格式:git config [--local|--global|--system] --rem…

MySQL面試準備——64頁pdf

本筆記為以前整理的零碎的關于Mysql的知識點,有深入源碼的也有淺層的八股。已經被我整理成了一個pdf。 實習崗位正好也是和數據庫內核有關的,之后應該還會更新。做個整理,方便秋招的時候快速回顧吧。 鏈接:鏈接 提取碼&#xff1a…

python點圖_Python | 點圖

python點圖The dot plot is a type of data representation in which each data-point in the figure is represented as a dot. Dot plot underlies discrete functions unlike a continuous function in a line plot. Each value could be correlated but cannot be connecte…

SAP-MM:發票、貸方憑證、事后借記、后續貸記

發票和事后借記 相同點:增加對供應商的應付款 不同點:針對同一訂單收貨,發票要先于事后借記(事后借記是對供應商后期發票金額的補充);發票和金額、訂單數量有關系,而事后借記只是訂單金額調整的…

Dijkstra for MapReduce (1)

<math xmlns"http://www.w3.org/1998/Math/MathML"><mi>x</mi><mo>,</mo><mi>y</mi><mo>&#x2208;<!-- ∈ --></mo><mi>X</mi> </math> 準備研究一下Dijkstra最短路徑算法Hadoop上…

sql的外鍵約束和主鍵約束_SQL約束

sql的外鍵約束和主鍵約束SQL | 約束條件 (SQL | Constraints) Constraints are the guidelines implemented on the information sections of a table. These are utilized to restrict the kind of information that can go into a table. This guarantees the precision and …

nios pio interrupt 的使能

關于nios 中的中斷&#xff0c;因為要16c550中需要nios的中斷環境去測試&#xff0c;所以就用到了中斷。 硬件&#xff1a;在nios中添加硬件PIO,但是要使能中斷功能。如下圖所示&#xff1a; 系統列化&#xff0c;PIO的連接就不說了。但是要注意兩地方&#xff1a;edge type&am…

《單線程的build hash table、write rows to chunks、hash join的步驟以及流程圖》

Build Hash Table流程 1、初始化row buffer2、從build input table中讀一行3、若讀完build input table所有row&#xff0c;返回狀態READING_ROW_FROM_PROBE_item4、否則&#xff0c;向hash map中寫入一條row5、如果hash map 寫入成功&#xff0c;返回2&#xff0c;繼續執行6、…

在Scala的溪流

Scala | 流 (Scala | Streams) Stream in Scala is a type of lazy val. It is a lazy val whose elements are evaluated only when they are used in the program. Lazy initialization is a feature of Scala that increases the performance of the program. Scala中的Stre…

適合高速驅動電路的推挽電路

http://www.dzsc.com/data/html/2008-9-10/69023.html 圖1是使用NPN/PNP型晶體管的互補推挽電路&#xff0c;適于驅動功率MOSFET的門極。此電路雖然具有門極電流的驅動能力&#xff0c;但射極輸出波形不能比輸人信號快。 圖2是此電路的開關波形。它表示出tf、tr都快&#xff0c…

cholesky分解

接著LU分解繼續往下&#xff0c;就會發展出很多相關但是并不完全一樣的矩陣分解&#xff0c;最后對于對稱正定矩陣&#xff0c;我們則可以給出非常有用的cholesky分解。這些分解的來源就在于矩陣本身存在的特殊的 結構。對于矩陣A&#xff0c;如果沒有任何的特殊結構&#xff0…

socket編程常見函數使用方法

socket知識 有了IP地址&#xff0c;socket可知道是與哪一臺主機的哪一個進程通信 有了端口號&#xff0c;就知道是這個進程的哪一個套接字進行傳輸 應用進程使用描述符與它的套接字進行通信&#xff0c;也就是說一個進程創建一個套接字時就會返回一個套接字描述符 socket的…

需求變更流程不規范,項目早晚得完蛋

很多人&#xff0c;做的項目不少&#xff0c;但成功的不多。這是一個值得深思的問題。 項目為什么這么難做&#xff1f;需求蔓延&#xff0c;客戶難搞是基本原因。 如何解決上述問題&#xff1a; 1&#xff09;強化需求調研和項目設計在整個項目中的重要性 一般地&#xff0c;需…

html 表格套表格_HTML表格

html 表格套表格A table is a set of rows and columns, which could be created on a webpage in HTML, by <table> tag. The tabular representation of complex data makes it readable. 表格是一組行和列&#xff0c;可以通過<table>標簽在HTML網頁上創建。 復…