Mysql hash join之classic hash join CHJ过程详解

hash join的历史

优化器里的hash join算法在SQL Server、Oracle、postgress等数据库早已实现,而Mysql在8.0.18之后才支持。在8.0.18之前mysql只支持嵌套循环关联(nested loop join),这其中最简单就是简易嵌套循环关联simple nestloop join,随后mysql做了改进进而支持block nestloop join, index nestloop join and batched key access等算法,这也是hash join算法被推迟实现的部分原因。

hash join的概述

提到hash join之前自然得说Nestloopjoin,以两个表的关联为例,它其实是个双层循环,先遍历外层的表(n条),再拿每次对应的值去匹配、循环遍历内部的表(M条)。这样显然会有M*n的计算复杂度。如果能将外部表先装载到内存,然后再做内部表的匹配、遍历,计算的复杂度就会大大降低,这就是hash join的思想。

hash join的类型

hash join 从具体实现上又分为:

1经典hash join(In-Memory Join或classic hash join或CHJ)

2 磁盘分区hash join (On-Disk Hash Join)

3 Grace Hash Join

4 混合hash join(hybrid hash join)

hash join应用场景

hash join主要应用在以下条件:

1两个或多个表至少包含一个等值条件关联时。

2 关联的字段上没有索引。

3 关联条件可以是原始字段或者表达式(如 T1.col1+T1.col2 = T2.col3+T2.col4).

4 关联条件等号的两表只能出现一张表。

5 补充,可能使用到hash join的SQL写法示例:

 CREATE TABLE t1 (t1_1 INT, t1_2 INT);CREATE TABLE t2 (t2_1 INT, t2_2 INT)SELECT * FROM t1 JOIN t2 ON (t1.t1_1 = t2.t2_1);SELECT * FROM t1 JOIN t2 ON (t1.t1_1 = t2.t2_1 AND t1.t1_2 = t2.t2_2);SELECT * FROM t1 JOIN t2 ON (t1.t1_1 = t2.t2_1 AND t2.t2_2 > 43);SELECT * FROM t1 JOIN t2 ON (t1.t1_1 + t1.t1_2 = t2.t2_1);SELECT * FROM t1 JOIN t2 ON (FLOOR(t1.t1_1 + t1.t1_2) = CEIL(t2.t2_1 = t2.t2_2));

In-Memory Join classic hash join

经典hash join(classic hash join)简称CHJ,该算法由两部分构成,一是构建哈希表(hash table)过程,二是探测、匹配(probe)过程。

以有如下查询和表格结构为例:

CREATE TABLE t1 (foo INT);

CREATE TABLE t2 (bar INT);

insert into t1 values(12);

insert into t2 values(34);

… ...  -- 插入数据省略

SELECT * FROM t1 JOIN t2 on (t1.foo = t2.bar);

构建哈希表:

1 当两个表以含等值条件方式关联时其中一个表会被指定为构建表,该表会以哈希表(哈希的值来自于等值条件里的字段)的形式读入内存。

2 假设这里t1表被指定为构建表,那么将会通过哈希函数产生哈希表,这里t1的foo字段是是哈希函数里的键。

探测阶段:

此时join里的另外个表即t2作为探测表,在构建完成后,开始从t2探测表作为输入。这时以t2的bar (t1、t2两表关联时t2的字段)作为哈希的键,同时该键是用来匹配内存里的t1生成的哈希表。一旦匹配到记录则意味着找到目标,这个按照每一行匹配的过程就做探测过程。

In-Memory Join过程示意

构建阶段示例

探测阶段示例​​​​

执行计划查看In-Memory Join

EXPLAIN ANALYZE
SELECT CountryCode, country.Name AS Country,
city.Name AS City, city.District
FROM world.country IGNORE INDEX (Primary)
INNER JOIN world.city IGNORE INDEX (CountryCode)
ON city.CountryCode = country.Code
WHERE Continent = 'Asia';-- 数据库来自mysql官网示例数据库world
-- 结果
EXPLAIN
-> Inner hash join (world.city.CountryCode = world.country.`Code`)  (cost=13870.82 rows=595) (actual time=58.807..134.662 rows=1766 loops=1)-> Table scan on city  (cost=0.80 rows=4046) (actual time=30.193..95.386 rows=4079 loops=1)-> Hash-> Filter: (world.country.Continent = 'Asia')  (cost=30.90 rows=34) (actual time=21.446..28.489 rows=51 loops=1)-> Table scan on country  (cost=30.90 rows=239) (actual time=21.435..28.338 rows=239 loops=1)

执行示例

 过程介绍

Step1:Country的Code字段会被哈希函数哈希并保存在关联缓存(即哈希表)内(join buffer)。

Step2:然后通过和step1里一样的哈希函数哈希的字段CountryCode进行表扫描(table scan)遍历city表里的每一行。

Mysql 优化器内部JOIN算法hash join Nestloopjoin及classic hash join CHJ过程详解相关推荐

  1. Mysql 优化器内部JOIN算法hash join On-Disk Hash Join Grace Hash Join Hybrid hash join过程详解

    Mysql 各种hash join算法讲解 hash join的概述 提到hash join之前自然得说Nest loop join,以两个表的关联为例,它其实是个双层循环,先遍历外层的表(n条),再 ...

  2. MySQL优化器如何预估查询成本

    MySQL有哪些查询成本 MySQL 执行一个查询可以有不同的执行方案.在我们开发过程中,所有写过的sql语句都会丢给MySQL端的优化器.由优化器判断并选择其中成本最低,或者说代价最低的那种方案去真 ...

  3. MySQL优化器_MySQL查询优化器

    MySQL优化器 MySQL架构图 讲到MySQL,就绕不开他的架构图.MySQL是一个经典的C/S架构.服务器这边分两层:第一层是Server层,第二层是存储引擎.Server层处理主要的业务操作流 ...

  4. MySQL优化器:index merge介绍

    在MySQL官方手册上,关于index merge的介绍非常非常少.甚至还有不少误导的地方,这次把5.1版本关于此类优化处理的代码细看了一遍,以案例的方式介绍了各种实用index merge访问类型的 ...

  5. mysql not in优化_98%的人不知道的MySQL优化器原理

    ​| 作者 梁东阳,数据库研发中心数据库内核工程师,负责腾讯云MySQL的内核开发. 在日常运维中,相信不少人都收藏了很多关于查询优化的方法论和小技巧,但是仔细想想,你真的了解这些优化背后的原理吗? ...

  6. MySQL优化器选错索引情况

    MySQL优化器选错索引情况 1. 优化器选错索引 2. 优化器的逻辑 3. 索引选择异常和处理 1. 优化器选错索引 之前MySQL架构以及执行sql查询语句介绍过MySQL优化器可以帮助我们优化s ...

  7. MySQL 优化器原来是这样工作的

    文章目录 优化器概述 逻辑转换 基于成本的优化 控制优化程度 设置成本常量 数据字典与统计信息 控制优化行为 优化器和索引提示 总结 大家好,我是只谈技术不剪发的 Tony 老师.我们在 MySQL ...

  8. mysql优化器怎么选择索引,为什么MySQL查询优化器会选择聚集主索引上的二级索引?...

    为什么Mysql优化器在执行'select * from lookup'而没有order by子句时选择二级索引. 它只是一个侥幸,或者这是一个幕后优化,假设你添加了一个二级索引,它比主键更重要. 我 ...

  9. mysql优化器放弃索引场景,MYSQL索引优化(索引失效场景)

    学习mysql是作为一名Java工程师必不可少的事情,但是我们只认识mysql的增删查改建表等等的sql语句其实远远不够的,对于进阶mysql来说,索引是一个很重要的部分.下面我们就来说一下在mysq ...

最新文章

  1. R语言ggplot2可视化:使用gganimate包和gapminder包为生成的动画文件gif设置尺寸、分辨率
  2. 3种时间序列混合建模方法的效果对比和代码实现
  3. 卫星发现一个重要信号:路上货车跑起来
  4. 那些做的“不够好”的父母,他们可能已经做到了自己的100分
  5. Java中的static———静态变量
  6. eoj程序设计基础(基于 C 语言)1067
  7. go语言爬虫教程python_Go语言爬虫 - Go语言中文网 - Golang中文社区
  8. xftp怎么有root权限_许多人都不懂的Linux系统里的特殊权限!!你真的了解嘛?...
  9. 第二节 CSS入门介绍
  10. (Android开发辅助工具)动态广播注册解注工具
  11. 汽车汽配行业DMS渠道商系统精准掌握渠道库存,提升市场响应能力
  12. 电力仿真需要学的软件?5款有实力的电力仿真软件
  13. win7系统使用高版本node.js
  14. 新能源车车牌识别c++
  15. 华为鸿蒙魔法闪投大小屏幕互动,「老熊科普」魔法闪投,荣耀智慧屏就是你的“超级大手机”...
  16. 十三届蓝桥杯基础知识大全
  17. 闲鱼如何保障交易链路质量
  18. 财路网每日原创推送:隐私计算让人工智能更智能
  19. python pdf转word的两种方法
  20. 约旦稳居B组头名 澳大利亚绝杀叙利亚出线

热门文章

  1. wxWidgets:wxFrame类用法
  2. 一个简单的 Hello world! 例子使用 boost::mpi::group 和 boost::mpi::broadcast()
  3. boost::mp11::mp_third相关用法的测试程序
  4. boost::mp11::mp_size相关用法的测试程序
  5. boost::math模块通过 Gauss 和 Gauss-Kronrod 正交的数值积分
  6. Boost:不受约束的bimap双图的测试程序
  7. VTK:可视化算法之PineRootDecimation
  8. VTK:PolyData之WeightedTransformFilter
  9. Qt发布到Google Play
  10. Qt Creator配置编辑器