因工作需要,对MySQL Hash Join的内部实现做了一些探索和实践,对这个由8.0.18开始引入的连接算法有了一定的了解,写文总结与各位大佬分享,欢迎大家指教。因篇幅较长,这份总结分成若干部分,我们今天先一起来看一下MySQL Hash join的变迁史。
爬了一下 MySQL worklog[1],并结合源码及各版本的实际使用,个人认为比较重要的worklogs为如下几个, 其它的变更一般围绕这些worklogs做的小调整或bugfixes,这里我们就不一一列举。
主要内容:
t1.a = t2.a),且join条件中的列不包含索引注:这里我认为官网的 Release Notes[2] 描述是不太准确的,以如下例子为例,虽然该查询包含了非等值连接条件(non-equi-join condition, 如 t1.a <> t2.a ,t1.a = 1, t2.a > 1 等),但实际查询中还是使用hash join的, 因为查询语句在解析执行过程中,可能会经历语句重写、sql优化等步骤,与表象上会有所不同,建议借助explain工具,查看实际上查询语句选择的join算法。
-- 版本:8.0.18
-- 在创建iterator时,t1.a > 1 会被当成表的过滤条件,而非inner join的join条件
-- 此查询仍使用了hash join(join 条件为空)
EXPLAIN FORMAT=tree SELECT * FROM t1 JOIN t2 ON t1.i > 1;
-> Inner hash join (cost=1.17 rows=3)
-> Table scan on t2 (cost=0.34 rows=2)
-> Hash
-> Filter: (t1.i > 1) (cost=0.65 rows=1)
-> Table scan on t1 (cost=0.65 rows=4)
主要内容:
non-equi-join conditions, 会被附为hash join的过滤条件:-- 版本:8.0.20
EXPLAIN FORMAT=tree SELECT * FROM t1 JOIN t2 ON t1.i <> t2.i;
-> Filter: (t1.i <> t2.i) (cost=1.10 rows=2)
-> Inner hash join (no condition) (cost=1.10 rows=2)
-> Table scan on t2 (cost=0.18 rows=2)
-> Hash
-> Table scan on t1 (cost=0.45 rows=2)
-- 版本:8.0.20
-- Left outer join
EXPLAIN FORMAT=tree SELECT * FROM t1 LEFT JOIN t2 ON t1.i=t2.i;
-> Left hash join (t2.i = t1.i) (cost=0.88 rows=4)
-> Table scan on t1 (cost=0.45 rows=2)
-> Hash
-> Table scan on t2 (cost=0.23 rows=2)
-- Right outer join(注:MySQL在parser阶段会将所有的right join改写为left join
-- 所以我们这里看到的explain为Left hash join
EXPLAIN FORMAT=tree SELECT * FROM t1 RIGHT JOIN t2 ON t1.i=t2.i;
-> Left hash join (t1.i = t2.i) (cost=0.88 rows=4)
-> Table scan on t2 (cost=0.45 rows=2)
-> Hash
-> Table scan on t1 (cost=0.23 rows=2)
-- Semijoin
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE (t1.i) IN (SELECT t2.i FROM t2);
-> Hash semijoin (t2.i = t1.i) (cost=0.83 rows=2)
-> Table scan on t1 (cost=0.45 rows=2)
-> Hash
-> Table scan on t2 (cost=0.18 rows=2)
-- Antijoin
EXPLAIN FORMAT=tree
SELECT * FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.i = t2.i);
-> Hash antijoin (t1.i = t2.i) (cost=1.10 rows=4)
-> Table scan on t2 (cost=0.45 rows=2)
-> Hash
-> Table scan on t1 (cost=0.45 rows=2)
"extra" condition的概念,部分 non-equi-join conditions会被当成Hash join iterator的extra condition, 在建hash table时,join key的计算不依赖这些条件,但会在hash查找到匹配项后,作为附加的过滤条件:-- 版本: 8.0.20
-- 注: t1.i > 1 会被放到hash join的 extra conditions中
EXPLAIN FORMAT=tree SELECT * FROM t1 LEFT JOIN t2 ON t1.i=t2.i AND t1.i > 1;
-> Left hash join (t2.i = t1.i), extra conditions: (t1.i > 1) (cost=0.88 rows=4)
-> Table scan on t1 (cost=0.45 rows=2)
-> Hash
-> Table scan on t2 (cost=0.23 rows=2)
相关源码:
// 代码版本:8.0.20 HEAD: commit 91a17cedb1ee880fe7915fb14cfd74c04e8d6588
// 文件名:sql/hash_join_iterator.cc
int HashJoinIterator::ReadNextJoinedRowFromHashTable() {
int res;
bool passes_extra_conditions = false;
do { // 所有匹配行都需要多做一个extra condition的判定,因为有可能存在不同行的记录
// 映射在同一个join key的情况,因此需要通过遍历逐条读取出符合extra conditions
// 的数据
res = ReadJoinedRow(); // 读取通过join key查找已经得到的匹配行(单行记录)
DBUG_ASSERT(res == 0 || res == -1);
if (res == 0) {
passes_extra_conditions = JoinedRowPassesExtraConditions();
if (thd()->is_error()) {
// Evaluation of extra conditions raised an error, so abort the join.
return 1;
}
if (!passes_extra_conditions) {
++m_hash_map_iterator;
}
}
} while (res == 0 && !passes_extra_conditions);
}
主要内容:
优化hash join table的创建方法
这里MySQL所说的“优化”, 实际上会更激进一点,这个版本中,MySQL直接使用了一个基于 robin hood hashing[3] 实现的 开源hash table[4] ,更换了原先的hash join table实现( from mem_root_unordered_multimap to robin_hood::unordered_flat_map)
优化内存管理和使用,降低了 on-disk hash 的频率,提高了内存有效使用率等(其他的改进内容及提升的效果可以参考MySQL 8.0.23的release notes[5] 以及 worklog #13459[6] 的Low Level Design页面)
本篇我们对MySQL hash join的3个重要变更做了简要的总结,算是对它的前世今生有了印象,谢谢各位阅读;之后让我们会结合具体的sql查询样例,去跟踪一下对应的代码执行流程,不日更新,敬请期待。
[1] MySQL worklog: https://dev.mysql.com/worklog/
[2] MySQL 8.0.18 release notes#optimizer: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-18.html#mysqld-8-0-18-optimizer
[3] robin hood hashing 算法介绍: https://programming.guide/robin-hood-hashing.html
[4] robin hood hasing 开源实现: https://github.com/martinus/robin-hood-hashing
[5] MySQL 8.0.23 release notes#optimizer: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-23.html#mysqld-8-0-23-optimizer
[6] MySQL worklog #13459: https://dev.mysql.com/worklog/task/?id=13459
Enjoy GreatSQL ?
GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
相关链接: GreatSQL社区 Gitee GitHub Bilibili
捉虫活动详情:https://greatsql.cn/thread-97-1-1.html
社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

微信:扫码添加
GreatSQL社区助手微信好友,发送验证信息加群。
)
互联网(信息去中心化)已颠覆世界,区块链(信用去中心化)却要颠覆互联网。一、概述区块链的本质是一个可共享的、可信的、每个人都可以检查的公开账本,但是没有任何一个单一的用户能够控制它。整个区块链系统的参与者一起来不断更新,让这本总账本为最新,它能够且只能按照严格的规则和公开的协议来进行修订。 互联网上的贸易,几乎都需要借助可以信赖的第三方信用机构来处理电子支付信息。这类系统仍然内生性地受制于“基于信用的模式”。区块链技术是构建比特币区块链网络与交易信息加密传输的基础技术,基于密码学原理而不基于信用,使得任何达成一致的双方直接支付,从而不需要第三方中介的参与。二、区块链起源(从比特币到区块链)20
Datawhale干货 作者:钱博文,中国移动云能力中心前言近年来,随着各大厂商的激烈角逐,预训练模型(ThePretrainedFoundationModels,PFMs)的发展可谓百花争鸣,谁都想在这场没有硝烟的战争中力压群雄,作为下游任务的基础,像BERT、GPT-3、MAE、DALLE-E和ChatGPT基于大规模数据训练,可为各种下游应用提供合理的参数初始化。这种迁移学习范式,让预训练模型以一种高傲的姿态在各种任务和应用中大放异彩。特别是最近大火ChatGPT,带着其独有的"思维”在各大领域乱杀,也将人工智能推向了新一轮高潮。本文也是从预训练模型成长的几个关键因素做了系统阐述,旨在
2022年11月,人工智能公司OpenAI推出了一款啥都会的聊天机器人:ChatGPT。它能聊天、能翻译、能做题,还会写情书、写论文、写小说……功能强大到马斯克都表示“我们离强大到危险的AI不远了”。ChatGPT是平地起高楼吗?是横空出世吗?当然不是。伴随着人工智能领域不断更新迭代的研究及不断增长的算力,才有了今天震撼世界的ChatGPT。悠络客自成立以来一直致力于建立前沿深度学习和算法平台。今天,我们就从技术角度出发,立足基本概念和基础研究,循序渐进对ChatGPT及相关热点内容进行介绍。#1NLP(自然语言处理)NLP的全称是NaturalLanguageProcessing(自然语言处
文章目录一、MySQL的由来二、MySQL的架构2.1客户端2.2服务器三、MySQL的主要组成部分3.1连接管理器3.2查询缓存3.3解析器3.4查询优化器3.5执行器3.6存储引擎四、MySQL的特点五、MySQL的应用场景六、总结一、MySQL的由来MySQL最初是由瑞典公司MySQLAB的MichaelWidenius和DavidAxmark开发的一款开源关系型数据库管理系统。MySQLAB的初衷是创造一个简单、快速、可靠的关系型数据库系统,以解决当时Web应用程序的需要。他们想要创造一个更简单、更强大的数据库系统,以取代当时主流的商业数据库系统。因此,MySQL在1995年诞生了。M
💂作者简介:THUNDER王,一名热爱财税和SAPABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAPABAP开发和数据库具有较深入的研究。💅文章概要:在此前文章中我们了解了SAP公司主要产品的时间线,众所周知,SAP公司所有产品都是基于ABAP语言来开发的,本篇文章着重要介绍的是SAP公司产品最重要的基石——ABAP。🤟每日一言:你可以遗憾,但是你绝对不能后悔。遗憾证明你努力过了,只是力有不逮。而后悔,只能说明你当时没努力
目录ChatGPT的前世今生——混沌初开ChatCPT简介ChatCPT是什么?ChatCPT的火爆程度ChatCPT火爆的原因1、功能强大,应用范围广泛2、训练数据量大,模型效果好3、优秀的商业模式OpenAI公司公司创始团队总结公众号文章链接参考链接:ChatGPT的前世今生——混沌初开ChatCPT简介人工智能技术的快速发展和广泛应用,已经改变了我们生活和工作的方式。其中,自然语言处理技术是人工智能技术的重要分支,为我们提供了更加智能、更加高效的交互方式。作为自然语言处理技术的一种,ChatCPT是一款由美国人工智能研究实验室OpenAI推出的自然语言处理工具,其强大的功能和广泛应用,使
互联网推动20世纪90年代是信息化时代,互联网开始普及,微软和英特尔挟PC以令天下,程序员率先使用互联网进行交流,互联网让信息交流成本大大降低,也让有共同爱好的人能够跨越地理限制拉近距离,以互联网的通信能力为基础,开源的软件开发模式变得流行。程序员利用业余时间进行软件开发,并开放源代码,引领了开源运动的潮流。Guido本人也是一位开源先锋,他维护了一个邮件列表,并把早期的Python用户都放在里面,早期Python用户就可以通过邮件进行群组交流,这些用户大多都是程序员,有相当优秀的开发能力,他们来自许多领域,有不同的背景,对Python也提出了各种各样的功能需求。由于Python相当开放,又容
最初的Python完全由Guido本人开发,一个有趣的传说也因此产生。相传Guido去Google面试Python程序员的时候简历上只写了一句话:“IwrotePython”。但是据说当时的HR大大貌似没理解啥意思,以为是说“我写过Python”,愣是面试了好多轮,才了解到也明白这句话的意思是:Python是我写的,简直不能再霸气了,这也被称为程序员界最牛叉的简历,被广为流传。之前Guido自己在他的G+上发了这样一条状态:Donotsendmeemaillikethis:HiGuido,IcameacrossyourresumeinaGooglewebsearch.Youseemtohave
很多朋友都问我学完基础知识以后怎样提高编程水平?当然是刷题啦!很多小伙伴都在纠结从哪里开始,今天给大家推荐一个身边朋友都在使用的刷题网站:点击进入牛客网刷题吧!今天是Java+经典算法进阶刷题的第四天,结合经典算法学习Java语法!一起升级打怪吧!!文章目录问题1:判断是不是二叉搜索树问题2:判断是不是完全二叉树问题3:判断是不是平衡二叉树问题4:二叉搜索树的最近公共祖先问题5:序列化二叉树总结(刷题经验分享)最近一直在练习二叉树的经典题目。为了巩固基础算法能力,同时也为了在面试中可以做到心中有数,我通过做题的方式让自己头脑保持清醒,让自己对基础算法题目时刻保持感觉。我几乎每天都通过刷题的方式
目录标题前言🐳Kubernetes到底是什么?🐬K8s的由来🐬K8s的工作方式🐬K8s主要组件🐋Master组件🐋Node组件🐳pod是什么?🐬pod的概念🐬控制管理器🐟控制管理--ReplicationController🐟控制管理--HPA(HorizontalPodAutoscaling)🐟StatefulSet🐟DaemonSet🐟Job🐬客户端(Client)—pod总结前言跟着博主从0到1学习K8s!我行,你也行!该文章是我的系列专栏的第一篇文,首先一下Kubernetes,然后进行pob的详细讲解。🐳Kubernetes到底是什么?下列介绍部分来自网络,如有侵权,告知删除!谢谢🐬