MYSQL hash join 终于等到她

2020-04-24 16:42:24 浏览数 (1)

MYSQL 的多表联合查询中,只有nest loop 的查询方式,让MYSQL 一致是被“嘲笑”的地方。MYSQL 8.018 后mysql 将拥有HASH JOIN 功能,虽然对比其他数据库来说,这并不新鲜,但对于MYSQL 算是划时代的里程碑。

原理之类的先不说,先看效果。建立两个存储过程,为C1 表和 C2表插入测试数据

代码语言:javascript复制
delimiter //
CREATE PROCEDURE insert_c1()
BEGIN
 DECLARE i int ;
DECLARE a varchar(20) ;
DECLARE b smallint ;
set i = 1;
begin 
WHILE i<=1000000 do
 set b = FLOOR(rand()*50);
if i mod 2 = 0 then
set a = 'good';
elseif i mod 3 = 0 then
set a = 'excellent';
elseif i mod 5 = 0 then
set a  = 'ordinary';
elseif i mod 4 = 0 then
set a = 'worsen';
else
set a = 'improvement';
end if;
if b < 20 then

set b = b   15;
end if;
INSERT into test.status(status,score) values (a,b);

set i = i   1;
END WHILE;
end;
 END
//
两个表结构是一样的
 CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` varchar(20) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_c1` (`c1`)
) ENGINE=InnoDB 

从图中可以清晰的看到查询已经走了hash join,那老的MYSQL DBA 可能会提出一个问题,到底这个hash join 比 nest loop 能好多少,可别和MYSQL 8 VS MYSQL 5.7一样,谁快还不一定。下面做了一个对比,可以清晰的看到在某些情况下,HASH JOIN 在没有索引的情况下,比添加了索引的NEST LOOP 的速度要快了一倍。

所以到这里,

1 hash join 的确是查询中需要的功能

2 hash join 的确在某些情况下 比 NEST LOOP 要快

在说明完这些问题后,我们的讲讲为什么

在MYSQL 中hash join的构造包含两个流程 1 build 2 probe

1建立的阶段就是将需要进行JOIN 的字段,进行一个HASH 值的计算,而到底哪个表要进行这样的计算,整体SIZE 小的表将被选中,在内存中构建这个计算好值的表

2 匹配的过程,从另外一个表中将字段的值进行计算,与内存中的值匹配的就被选中,否则就抛弃。

这样操作的好处也是显而易见的,大大缩减比对的次数

NEST LOOP 如果是 N * S 则 hash join 可以比对为N * distinct S 如果distinct S 变化的值越少,则表的查询速度越快。

当然这样还会产生另一个结果,就是我们可以在某些时候放弃JOIN 中建立索引了,如果建立了索引,则MYSQL 会倾向使用 NEST LOOP ,而不走HASH JOIN ,所以到了8.018 这个版本后,MYSQL 的查询优化,可能又要添加一条想法了。

当然如果想要这个功能,首先先查查你的数据库目前支持,或打开了这个功能没有。

那hash joinj就无敌了,哪里都能用 NO NO NO 要使用它是有限制的,我们下面吧索引删除

下面的查询看似和上面的差不多,但就是没有走HASH JOIN

所以需要记住三个地方是是否能使用HASH JOIN 的前提

1 没有索引

2 等值运算

3 INNER JOIN

0 人点赞