mysql8.0中关于hash join的文件有以下几个,一个个来分析。
hash_join_chunk
HashJoinChunk是用来存储行并落盘的类型,表分区成小文件时也可以用。
将列写入 HashJoinChunk 时,我们使用 StoreFromTableBuffers 将必要的列转换为适合存储在磁盘上的格式。
方便的是,StoreFromTableBuffers 创建了一个连续的字节范围和相应的长度,可以轻松有效地将其写到文件中。从文件中读回行时,LoadIntoTableBuffers() 用于将行放回表记录缓冲区。
具体用法如下:
HashJoinChunk chunk;
// 初始化chunk来保存给定表的数据,匹配标志设置为false
// 第一个参数用来指定存储的哪张表的数据,第二个参数用来指定每行需不需要有匹配标志
chunk.Init(tables, /*uses_match_flags=*/false);
// 表和chunk之间复制数据用的缓冲区
String buffer;
while (iterator->Read() == 0) {
// 将buffer中记录的数据转到chunk中
// 如果这个chunk被初始化为匹配标志为true,我们会在行前加一个匹配标志
chunk.WriteRowToChunk(&buffer, /*matched=*/false);
};
// 准备读取chunk中的第一行数据
chunk.Rewind();
bool match_flag;
// 将chunk中的数据导到buffer中
// 如果chunk被初始化为使用匹配标志,则行读取的匹配标志将存储在“match_flag”中。
chunk.LoadRowFromChunk(&buffer, &match_flag);
HashJoinChunk拥有几个接口:
// 初始化接口
bool Init(const pack_rows::TableCollection &tables, bool uses_match_flags);
// 返回chunk中存储的行数
ha_rows num_rows() const { return m_num_rows; }
// 将row写入chunk
bool WriteRowToChunk(String *buffer, bool matched);
// 从chunk中读入row
bool LoadRowFromChunk(String *buffer, bool *matched);
//刷新文件缓冲区,并准备读取文件。
bool Rewind();
看了一下WriteRowChunk的源码,思路还是很清楚的:
hash_join_buffer
HashJoinBuffer是用来存储一批行数据的。
行数据会存储在哈希表中,HashJoinBuffer会维护自己的MEM_ROOT,所有数据都会分配在这里。
考虑下面的sql:
SELECT t1.data FROM t1 JOIN t2 ON (t1.key = t2.key);
假设表“t2”存储在 HashJoinBuffer 中。这种情况下,t2.key就将作为哈希表键值,如果on条件中有多个等式,那么这些等式将一起组合为哈希表的键值。
使用函数接口 StoreFromTabl