如何干涉MySQL优化器使用hash join

  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。

  • 前言

  • 实验
  • 总结

前言

数据库的优化器相当于人类的大脑,大部分时候都能做出正确的决策,制定正确的执行计划,走出一条高效的路,但是它毕竟是基于某些固定的规则、算法来做的判断,有时候并没有我们人脑思维灵活,当我们确定优化器选择执行计划错误时该怎么办呢,语句上加hint,提示它选择哪条路是一种常见的优化方法。

我们知道Oracle提供了比较灵活的hint提示来指示优化器在多表连接时选择哪种表连接方式,比如 use_nlno_use_nl控制是否使用Nest Loop Join, use_hash, no_use_hash控制是否使用hash join。

但是MySQL长期以来只有一种表连接方式,那就是 Nest Loop Join,直到MySQL8.0.18版本才出现了hash join, 所以MySQL在控制表连接方式上没有提供那么多丰富的hint给我们使用, hash_joinno_hash_join的hint只是惊鸿一瞥,只在8.0.18版本存在,8.0.19及后面的版本又将这个hint给废弃了,那如果我们想让两个表做hash join该怎么办呢?

实验

我们来以MySQL8.0.25的单机环境做一个实验。建两个表,分别插入10000行数据,使用主键做这两个表的关联查询。

create table t1(id int primary key,c1 int,c2 int);
create table t2(id int primary key,c1 int,c2 int);
delimiter //
CREATE PROCEDURE p_test()
BEGIN
declare i int;
set i=1;
while i

查询一下两表使用主键字段关联查询时实际的执行计划,如下图所示:

如何干涉MySQL优化器使用hash join

查询一下两表使用非索引字段关联查询时实际的执行计划,如下图所示:

如何干涉MySQL优化器使用hash join

从执行计划可以看出,被驱动表的关联字段上有索引,优化器在选择表连接方式时会倾向于选择Nest Loop Join,当没有可用索引时倾向于选择hash join。

基于这一点那我们可以使用 no_index提示来禁止语句使用关联字段的索引。

如何干涉MySQL优化器使用hash join

从上面的执行计划可以看出使用no_index提示后,优化器选择了使用hash join。

当索引的选择性不好时,优化器选择使用索引做Nest Loop Join是效率是很低的。

我们将实验的两个表中c1列的数据做一下更改,使其选择性变差,并在c1列上建普通索引。

update t1 set c1=1 where id

当我们执行sql :

select t1.*,t2.* from t1 join t2 on t1.c1=t2.c1;

这个查询结果会返回大量数据,被驱动表的关联字段c1列的索引选择性差,此时选择hash join是更明智的选择,但是优化器会选择走Nest Loop Join。我们可以通过实验验证一下hash join 与 Nest Loop Join的性能差异。

如何干涉MySQL优化器使用hash join

可以看出使用hash join的耗时是使用Nest Loop Join的1/6,但是优化器根据成本估算时,使用Nest Loop Join的成本要比使用hash join的成本低很多,所以会去选择Nest Loop Join,这个时候就需要加上hint 提示禁止使用关联字段的索引,被驱动表上每次都全表扫描的代价是很高的,这样优化器估算后就会选择走hash join。

MySQL官方文档里提到用 BNLNO_BNL的hint提示来影响hash join的优化,但是经过实验证明,在表连接关联字段上没有可用索引时,优化器估算成本后不会对被驱动表使用BNL全表扫描的方式做嵌套循环连接,而是会选择使用hash join,那这样NO_BNL在这个场景下就没有用武之地了。

那么既然不用这个索引,把这个索引去掉不就可以了吗?为什么非要使用no_index的hint提示呢,我们要知道业务使用的场景何其多,此处不用,别处使用了这个索引效率可能会有大的提升啊,这个时候就凸显了hint的优势,只需要控制此语句的使用就好了。

总结

Nest Loop Join有其优势,它是response最快的连接方式,适用于返回数据量小的场景。当两个大表连接,返回大量数据,且关联字段的索引比较低效时,使用hash join就会比较高效,我们可以使用no_index的hint提示禁用关联字段的低效索引,促使优化器选择hash join。

Original: https://www.cnblogs.com/greatsql/p/16688860.html
Author: GreatSQL
Title: 如何干涉MySQL优化器使用hash join

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/598640/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MYSQL的Java操作器——JDBC

    在学习了Mysql之后,我们就要把Mysql和我们之前所学习的Java所结合起来 而JDBC就是这样一种工具:帮助我们使用Java语言来操作Mysql数据库 JDBC简介 首先我们…

    数据库 2023年6月14日
    079
  • windows bat

    windows bat windows bat netsh2-ipv4 新建文件夹 Windows 10 右下角时间显示时分秒 windows route 检测到以管理员权限运行 …

    数据库 2023年6月9日
    0102
  • Java中的SPI原理浅谈

    在面向对象的程序设计中,模块之间交互采用接口编程,通常情况下调用方不需要知道被调用方的内部实现细节,因为一旦涉及到了具体实现,如果需要换一种实现就需要修改代码,这违反了程序设计的&…

    数据库 2023年6月14日
    071
  • 多商户商城系统功能拆解21讲-平台端分销订单

    多商户商城系统,也称为B2B2C(BBC)平台电商模式多商家商城系统。可以快速帮助企业搭建类似拼多多/京东/天猫/淘宝的综合商城。 多商户商城系统支持商家入驻加盟,同时满足平台自营…

    数据库 2023年6月14日
    0103
  • jmeter-跨线程组全局变量

    需求:两个线程组(A线程组与B线程组)👉A线程组的变量信息被B线程组引用。 操作: 1. A线程组使用登录接口获取token、通过Json提取器获取到登录token, 然后添加&#…

    数据库 2023年6月14日
    089
  • Mybatis SqlNode源码解析

    1.ForEachSqlNode mybatis的foreach标签可以将列表、数组中的元素拼接起来,中间可以指定分隔符separator <select id="…

    数据库 2023年6月16日
    077
  • Java 线程创建与常用方法

    进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、…

    数据库 2023年6月16日
    067
  • MySQL操作题(mysql_V20190307)

    DB操作题(mysql_V20190307) 登陆数据库 MYSQL -H LOCALHOST -U ROOT -P 创建DEMO01数据库 CREATE DATABASE DEM…

    数据库 2023年6月9日
    059
  • Java中的命名规则

    在查找java命名规则时,未在国内相关网站查找到较为完整的文章,这是一篇国外程序开发人员写的java命名规则的文章,原文是英文写的,为了便于阅读,遂翻译为汉语,以便帮助国内开发者有…

    数据库 2023年6月11日
    092
  • 分割list,将集合按规定个数分为n个部分。

      /** * 按指定大小,分隔&#x9…

    数据库 2023年6月11日
    077
  • 使用JMeter进行MySQL的压力测试

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。 GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。 前言 1. JMeter安装 2…

    数据库 2023年5月24日
    095
  • Mysql数据库存取原理及性能优化

    一、Mysql的系统架构图 二、Mysql存储引擎 Mysql中的数据是通过一定的方式存储在文件或者内存中的,任何方式都有不同的存储、查找和更新机制,这意味着选择不同的方式对于数据…

    数据库 2023年6月14日
    0102
  • MySQL45讲-2-一条SQL更新语句是如何执行的?

    前面我们了解了SQL查询语句是如何执行的,一条SQL查询语句的过程需要经过连接器、分析器、优化器、执行器等功能模块,最终到达存储引擎。 在MySQL中,可以恢复到半个月内的任何一个…

    数据库 2023年5月24日
    093
  • 分析了2020年3万多条的微博热搜,我看到了什么

    前言 2020年是艰难的一年,但即使再难,也都过去了。 分析一下2020年的新闻热搜,可以大致了解网民都在关注什么。 微博热搜以娱乐为主,头条的热搜更偏向民生与时事。今天,我们先分…

    数据库 2023年6月16日
    099
  • Github 星标 8K+ 这款国人开源的 Redis 可视化管理工具,真香…

    做程序员就少不了与一些工具打交道,比如:监控工具、管理工具等,有些工具是命令行界面,有些工具是可视化界面,反正都是可以能够满足日常使用的功能需求。 对于redis管理工具来说,也有…

    数据库 2023年6月9日
    0112
  • Mysql面试总结

    转载自:https://www.cxyxiaowu.com/16302.html Q1:MySQL 的逻辑架构了解吗? 第一层是服务器层,主要提供连接处理、授权认证、安全等功能。 …

    数据库 2023年5月24日
    099
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球