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.mzph.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网页上创建。 复…