【MySQL精通之路】SQL优化(1)-查询优化(4)-Hash联接查询

 主博客:

【MySQL精通之路】SQL优化(1)-查询优化-CSDN博客

上一篇:

【MySQL精通之路】SQL优化(1)-查询优化(3)-索引合并-CSDN博客

下一篇:

【MySQL精通之路】SQL优化(1)-查询优化(5)-引擎条件下推-CSDN博客


默认情况下,MySQL(8.0.18及更高版本)尽可能使用Hash散列联接。可以使用BNLNO_BNL优化器提示中的一个来控制是否使用散列联接

或者通过设置optimizer_switch服务器系统变量中的block_nested_loop=onblock_nested_roop=off为来控制是否采用Hash联接。

注意:

MySQL 8.0.18支持在optimizer_switch中设置hash_join标志,以及优化器提示HASH_JOIN和NO_HASH_JOIN。

在MySQL 8.0.19及更高版本中,这些都不再有任何效果。

从MySQL 8.0.18开始,MySQL对任何查询都使用散列联接,其中每个联接都有一个等联接条件,并且其中没有可应用于任何联接条件的索引,例如以下查询:

SELECT *FROM t1JOIN t2ON t1.c1=t2.c1;

当有一个或多个索引可用于单表谓词时,也可以使用散列联接。

散列联接通常比MySQL的早期版本中使用的块嵌套循环算法

(请参见块嵌套循环联接算法)

更快

从MySQL 8.0.20开始,删除了对块嵌套循环的支持,并且使用散列联接替代块嵌套循环

在刚刚显示的示例和本节中的其余示例中,我们假设使用以下语句创建了三个表t1、t2和t3:

CREATE TABLE t1 (c1 INT, c2 INT);
CREATE TABLE t2 (c1 INT, c2 INT);
CREATE TABLE t3 (c1 INT, c2 INT);

您可以看到,使用EXPLAIN使用了散列联接,如下所示:

mysql> EXPLAIN-> SELECT * FROM t1->     JOIN t2 ON t1.c1=t2.c1\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t1partitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 1filtered: 100.00Extra: NULL
*************************** 2. row ***************************id: 1select_type: SIMPLEtable: t2partitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 1filtered: 100.00Extra: Using where; Using join buffer (hash join)

 (在MySQL 8.0.20之前,有必要包含FORMAT=TREE选项,以查看Hash联接是否用于给定联接。)

EXPLAIN ANALYZE还显示有关所使用的Hash联接的信息。

Hash联接也用于涉及多个联接的查询,只要每对表至少有一个联接条件是等联接,就像这里显示的查询一样:

SELECT * FROM t1JOIN t2 ON (t1.c1 = t2.c1 AND t1.c2 < t2.c2)JOIN t3 ON (t2.c1 = t3.c1);

在如刚才所示的使用内联接的情况下,任何非等联接的额外条件都将在执行联接后作为过滤器应用。(对于外部联接,如左联接半联接反联接,它们被打印为联接的一部分。)这可以在EXPLAIN的输出中看到:

mysql> EXPLAIN FORMAT=TREE-> SELECT *->     FROM t1->     JOIN t2->         ON (t1.c1 = t2.c1 AND t1.c2 < t2.c2)->     JOIN t3->         ON (t2.c1 = t3.c1)\G
*************************** 1. row ***************************
EXPLAIN: -> Inner hash join (t3.c1 = t1.c1)  (cost=1.05 rows=1)-> Table scan on t3  (cost=0.35 rows=1)-> Hash-> Filter: (t1.c2 < t2.c2)  (cost=0.70 rows=1)-> Inner hash join (t2.c1 = t1.c1)  (cost=0.70 rows=1)-> Table scan on t2  (cost=0.35 rows=1)-> Hash-> Table scan on t1  (cost=0.35 rows=1)

从刚刚显示的输出中也可以看出,多个Hash联接可以(并且)用于具有多个等联接条件的联接。

在MySQL 8.0.20之前,如果任何一对联接的表都没有至少一个等联接条件,则不能使用哈希联接,并且使用较慢的块嵌套循环算法。在MySQL 8.0.20及更高版本中,这种情况下会使用散列联接,如下所示:

mysql> EXPLAIN FORMAT=TREE-> SELECT * FROM t1->     JOIN t2 ON (t1.c1 = t2.c1)->     JOIN t3 ON (t2.c1 < t3.c1)\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t1.c1 < t3.c1)  (cost=1.05 rows=1)-> Inner hash join (no condition)  (cost=1.05 rows=1)-> Table scan on t3  (cost=0.35 rows=1)-> Hash-> Inner hash join (t2.c1 = t1.c1)  (cost=0.70 rows=1)-> Table scan on t2  (cost=0.35 rows=1)-> Hash-> Table scan on t1  (cost=0.35 rows=1)

(本节稍后将提供其他示例。)

散列联接也适用于笛卡尔乘积——也就是说,当没有指定联接条件时,如图所示:

mysql> EXPLAIN FORMAT=TREE-> SELECT *->     FROM t1->     JOIN t2->     WHERE t1.c2 > 50\G
*************************** 1. row ***************************
EXPLAIN: -> Inner hash join  (cost=0.70 rows=1)-> Table scan on t2  (cost=0.35 rows=1)-> Hash-> Filter: (t1.c2 > 50)  (cost=0.35 rows=1)-> Table scan on t1  (cost=0.35 rows=1)

 在MySQL 8.0.20及更高版本中,联接不再需要包含至少一个等联接条件才能使用哈希联接。这意味着可以使用哈希联接优化的查询类型包括以下列表中的查询类型(带示例):

非等-内连接:

mysql> EXPLAIN FORMAT=TREE SELECT * FROM t1 JOIN t2 ON t1.c1 < t2.c1\G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t1.c1 < t2.c1)  (cost=4.70 rows=12)-> Inner hash join (no condition)  (cost=4.70 rows=12)-> Table scan on t2  (cost=0.08 rows=6)-> Hash-> Table scan on t1  (cost=0.85 rows=6)

半连接:

mysql> EXPLAIN FORMAT=TREE SELECT * FROM t1 ->     WHERE t1.c1 IN (SELECT t2.c2 FROM t2)\G
*************************** 1. row ***************************
EXPLAIN: -> Hash semijoin (t2.c2 = t1.c1)  (cost=0.70 rows=1)-> Table scan on t1  (cost=0.35 rows=1)-> Hash-> Table scan on t2  (cost=0.35 rows=1)

 反联接:

mysql> EXPLAIN FORMAT=TREE SELECT * FROM t2 ->     WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.c1 = t2.c1)\G
*************************** 1. row ***************************
EXPLAIN: -> Hash antijoin (t1.c1 = t2.c1)  (cost=0.70 rows=1)-> Table scan on t2  (cost=0.35 rows=1)-> Hash-> Table scan on t1  (cost=0.35 rows=1)1 row in set, 1 warning (0.00 sec)mysql> SHOW WARNINGS\G
*************************** 1. row ***************************Level: NoteCode: 1276
Message: Field or reference 't3.t2.c1' of SELECT #2 was resolved in SELECT #1

左外连接:

mysql> EXPLAIN FORMAT=TREE SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1\G
*************************** 1. row ***************************
EXPLAIN: -> Left hash join (t2.c1 = t1.c1)  (cost=0.70 rows=1)-> Table scan on t1  (cost=0.35 rows=1)-> Hash-> Table scan on t2  (cost=0.35 rows=1)

右外联接(注意MySQL将所有右外联接重写为左外联接):

mysql> EXPLAIN FORMAT=TREE SELECT * FROM t1 RIGHT JOIN t2 ON t1.c1 = t2.c1\G
*************************** 1. row ***************************
EXPLAIN: -> Left hash join (t1.c1 = t2.c1)  (cost=0.70 rows=1)-> Table scan on t2  (cost=0.35 rows=1)-> Hash-> Table scan on t1  (cost=0.35 rows=1)

默认情况下,MySQL 8.0.18及更高版本尽可能使用散列联接。可以使用BNL和NO_BNL优化器提示之一来控制是否使用散列联接。

(MySQL 8.0.18支持hash_join=onhash_join=off作为optimizer_switch服务器系统变量设置的一部分,以及优化器提示HASH_JOIN 或NO_HASH_JOIN。在MySQL 8.0.19及更高版本中,这些不再有任何作用。)

散列联接的内存使用可以使用join_buffer_size系统变量进行控制;

哈希联接使用的内存不能超过这个数量。

当哈希连接所需的内存超过可用量时,MySQL会使用磁盘上的文件来处理。

如果发生这种情况,您应该注意,如果哈希联接无法放入内存,并且它创建的文件数超过了为open_files_limit设置的文件数,则联接可能不会成功。

为避免此类问题,请进行以下任一更改:

增加join_buffer_size,使散列联接不会溢出到磁盘。

增加open_files_limit。

从MySQL 8.0.18开始,哈希连接连接缓冲区递增分配的;

因此,您可以将join_buffer_size设置得更高,而不需要小查询分配大量RAM,但外部联接会分配整个缓冲区

在MySQL 8.0.20及更高版本中,散列联接也用于外部联接(包括反联接和半联接),因此这不再是问题。

补充:

博主PS:

上文内容来自官网,刚读的时候肯定会懵逼。

那Hash联接的存在意义和功能是什么呢?

我们知道连表查询的时候,我们会以on 某个字段 语句来连接两张表。

hash联接就是数据库在这里建立了一张hash表,用于存放这个on的条件结果,

那么循环到下一个关联记录的时候,如果还是相同的关联条件的时候,就直接从hash表里定位结果。

一般建立小表的hash映射。比如小表是1000条记录,大表是1万条记录。小表我如果做hash了查询小表的时间复杂度是不是O(1)?大表没有hash我的查找是不是O(n)。两表连接查,就是1万次for循环。

大小表要是循环嵌套的方式连表判断,时间复杂度是不是就O(n^2),就是1000万次查询。

但是这里我小表hash计算位置了。那时间复杂度就只有大表的O(n)。你可以理解为双层for循环,变成单层了。

这就是Hash联接查询的意义。

当然也可以两表都建立hash。只是会耗费hash计算时间,和内存而已。但是查询更快。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/15252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

clangd failed: Couldn‘t build compiler instance问题解决!!!

如果其他人的博客不能解决问题&#xff0c;可以试试我的解决方案&#xff1a; 修改compile_commands.json中cc为arm-linux-gnueabihf-gcc&#xff0c; 例如&#xff1a; 之后&#xff0c;clangd就能用了&#xff0c;虽然输出也会报错&#xff0c;但好歹能用了

【qt】标准型模型 下

标准型模型 一.前言二.预览数据1.获取表头2.获取数据项 三.保存文件1.文件对话框获取保存文件名2.用文件名初始化文件对象3.打开文件对象4.用文件对象初始化文本流5.写入数据 四.格式1.居右2.居中3.居左4.粗体 五.模型的信号1.解决粗体action问题2.状态栏显示信息 六.总结 一.前…

什么是高精度定位平板?

高精度定位平板是一种结合了高精度定位技术和强大计算能力的平板电脑&#xff0c;广泛应用于测绘、地理信息系统&#xff08;GIS&#xff09;、精准农业、工程建设和公共安全等领域。其核心特点在于能够提供亚米级甚至厘米级的定位精度&#xff0c;远超普通GPS设备的精度。 高…

C++容器之无序集(std::unordered_set)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 iterators3.4 capacity3.5 find3.6 count3.7 equal_range3.8 emplace3.9 emplace_hint3.10 insert3.11 erase3.12 clear3.13 swap3.14 bucket_count3.15 max_bucket_count3.16 bucket_size3.17 bucket3.18 load_fa…

Kiwi浏览器 - 支持 Chrome 扩展的安卓浏览器

​【应用名称】&#xff1a;Kiwi浏览器 - 支持 Chrome 扩展的安卓浏览器 ​【适用平台】&#xff1a;#Android ​【软件标签】&#xff1a;#Kiwi ​【应用版本】&#xff1a;124.0.6327.2 ​【应用大小】&#xff1a;233MB ​【软件说明】&#xff1a;一款基于开源项目 Chr…

vue3 vite动态根据字符串加载组件

1 原理 import.meta.glob() 其实不仅能接收一个字符串&#xff0c;还可以接收一个字符串数组&#xff0c;就是匹配多个位置 let RouterModules import.meta.glob(["/src/view/*/*.vue", "/src/view/*.vue"]);这样我们就拿到了相对路劲的组件对象&#xf…

[激光原理与应用-93]:激光焊接检测传感器中常用的聚焦镜、分色镜、分光镜、滤波镜

目录 一、聚焦镜 1.1 原理及作用 1.2 性能指标 1.3 应用 1.4 类型 二、分色镜 2.1 原理及应用 2.2 种类 2.3 特点 2.4 注意事项 2.5 性能指标 三、分光镜 ​编辑 3.1 分光镜的类型 3.2 分光镜的工作原理 3.3 分光镜的应用 3.4 分光镜的参数 3.5 分光镜的优点…

物业可视化大屏,终于让繁琐数据一手掌握啦。

物业可视化大屏通常需要展示与物业管理相关的数据&#xff0c;以便管理人员和业主能够实时监控和分析物业运营情况。以下是一些常见的物业可视化大屏所展示的数据类别&#xff1a; 1. 房产信息&#xff1a; - 房产总数、出租率、空置率等。- 房产面积分布情况。- 房产类型、户…

ES升级--01--环境准备和安装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Linux 单机1.官网下载 Elasticsearchhttps://www.elastic.co/cn/downloads/past-releases/#elasticsearch 2.解压软件3.创建用户设置用户 es 密码 es赋权ES用户数据…

MySQL——约束与表的设计基础

前言 本篇文章主要介绍数据库约束以及数据库中有关表设计的一些基础知识&#xff0c;文章会尽量都用实例进行直观的讲解与展示每个知识点的意义&#xff0c;现在就开始今天的学习吧&#xff01;&#xff01; 一、数据库约束 1.约束概述 约束&#xff0c;就是在创建表的时候给…

Spring Boot 01:Spring Boot 项目的两种创建方式

一、前言 记录时间 [2024-05-25] 本文讲述 Spring Boot 项目的两种创建方式&#xff0c;分别是 IDEA 和官网。 由 Spring 官网知&#xff0c;当前 Spring Boot 的最新版本为 3.3.0&#xff0c;需要最低 JDK 版本为 17。 Spring 官网项目创建地址JDK 17 版本下载地址 准备工作…

软考-下午题-试题二、三

主要是最后一问的不同解答 1、父图子图平衡 1、员工关系是否存在传递依赖&#xff1f;用100字以内的文字说明理由。2019 2、在职员关系模式中&#xff0c;假设每个职员有多名家属成员&#xff0c;那么职员关系模式存在什么问题&#xff1f; 应如何解决&#xff1f;2020 职员关系…

二十八篇:嵌入式系统实战指南:案例研究与未来挑战

嵌入式系统实战指南&#xff1a;案例研究与未来挑战 1. 引言 1.1 嵌入式系统的重要性及其应用广度 在当今快速发展的技术领域中&#xff0c;嵌入式系统扮演着至关重要的角色。这些系统是专门设计的计算机硬件和软件的组合&#xff0c;旨在执行特定任务&#xff0c;如控制、监…

青鸟云报修系统:实现高效、便捷的维修申请处理

在日常生活和工作中&#xff0c;故障报修难免会遇到&#xff0c;售后报修服务则成为了解决问题的关键。纸质化售后报修维修申请单&#xff0c;作为报修流程中的重要一环&#xff0c;在一定程度上能够记录和追踪售后报修维修流程&#xff0c;但在实际操作过程中却存在着诸多弊端…

速看!!!24上软考-信息系统项目管理师真题回忆,考点已更新

整理了24上半年软考高级信息系统项目管理师的考试真题&#xff0c;软考一个批次一套题&#xff0c;现在都是机考&#xff0c;收集题目比较困难&#xff0c;希望能给个小小的赞支持一下。 注意&#xff1a;当天考试的宝子们可以对答案预估分数&#xff01;后面场次的宝子可以提…

llama-factory学习个人记录

框架、模型、数据集准备 1.llama-factory部署 # 克隆仓库 git clone https://github.com/hiyouga/LLaMA-Factory.git # 创建虚拟环境 conda create --name llama_factory python3.10 # 激活虚拟环境 conda activate llama_factory # 安装依赖 cd LLaMA-Factory pip install -…

Java虚拟机揭秘-底层驱动力,性能保障!

Java虚拟机作为Java技术体系的核心组成部分&#xff0c;其重要性不言而喻。它不仅为Java提供了跨平台的能力&#xff0c;更是Java程序运行的基石。本文将为您深入解析Java虚拟机的工作原理、作用和应用场景&#xff0c;并通过生动的实例让您彻底理解这一关键技术。 一、Java虚拟…

学习thinkphp的循环标签

1.FOREACH标签 foreach标签的用法和PHP语法非常接近&#xff0c;用于循环输出数组或者对象的属性&#xff0c;用法如下&#xff1a; $list User::all(); View::assign(list,$list); 模板文件中可以这样输出 {foreach $list as $key>$vo } {$vo.id}:{$vo.name} {/foreac…

element-plusDate Picker 日期选择器获取年月日

代码逻辑 对选择日期选择后进行搜索 &#xff1a; function dataValue(value) {console.log(value);scenic_list.value arrlist.value.filter(function (item) {// 判断是否满足搜索条件if (String(item.create_time).indexOf(String(value)) > -1) {return scenic_list}}…

Java 说唱歌手

Yo yo yo&#xff0c;欢迎来到Java地带&#xff0c;技术的盛宴开启&#xff0c; 从JDK到JVM&#xff0c;我们构建的是数字世界的奇迹。 Spring Boot启动&#xff0c;微服务架构轻盈起舞&#xff0c; IoC解耦依赖&#xff0c;AOP切面如丝般顺滑。 Maven管理依赖&#xff0c;Gra…