当前位置: 首页 > news >正文

MySQL进阶-关联查询优化

采用左外连接

下面开始 EXPLAIN 分析

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

结论:type 有All  ,代表着全表扫描,效率较差

 添加索引优化

ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】,可以避免全表扫描
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

可以看到第二行的 type 变为了 ref,rows 也变成了优化比较明显。这是由左连接特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有,所以 右边是我们的关键点,一定需要建立索引 。  也就是left join 右边所关联的表的关联字段一定要建立索引

 只是对左边的表建立索引的话,是没有效果的,可以通过rows这一列看到,type表要读取的记录仍然是20条。

ALTER TABLE `type` ADD INDEX X (card); #【驱动表】,无法避免全表扫描
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

把右边的表的索引删除,可以发现现在又要走全表扫描了 

DROP INDEX Y ON book;
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

 采用内连接

删除先前的索引

drop index X on type;
drop index Y on book;(如果已经删除了可以不用再执行该操作)

换成 inner join(MySQL自动选择驱动表)

EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

 添加索引优化

向book表添加索引后,book自动成为被驱动表,提高了查询效率。

ALTER TABLE book ADD INDEX Y (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

如果新增了type表的索引,此时两个表都有索引,优化器会选择小数据量的表作为驱动表,用来驱动大表。

ALTER TABLE type ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

对于内连接来说,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的,接下来把type表的索引删了。可以看到有索引的book表又作为了被驱动表

DROP INDEX X ON `type`;
EXPLAIN SELECT SQL_NO_CACHE * FROM TYPE INNER JOIN book ON type.card=book.card;

 向type表里面添加索引,此时又变成了被驱动表了

ALTER TABLE `type` ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON type.card=book.card;

join语句原理

join方式连接多个表,本质就是各个表之间数据的循环匹配。MySQL5.5版本之前,MySQL只支持一种表间关联方式,就是嵌套循环(Nested Loop Join)。如果关联表的数据量很大,则join关联的执行时间会很长。在MySQL5.5以后的版本中,MySQL通过引入BNLJ算法来优化嵌套执行。

驱动表和被驱动表

驱动表就是主表,被驱动表就是从表、非驱动表。

  • 对于内连接来说:

A一定是驱动表吗?不一定,优化器会根据你查询语句做优化,决定先查哪张表。先查询的那张表就是驱动表,反之就是被驱动表。通过explain关键字可以查看。

SELECT * FROM A JOIN B ON ...
  • 对于外连接来说:
SELECT * FROM A LEFT JOIN B ON ...
# 或
SELECT * FROM B RIGHT JOIN A ON ... 

Simple Nested-Loop Join (简单嵌套循环连接)

算法相当简单,从表A中取出一条数据1,遍历表B,将匹配到的数据放到result.. 以此类推,驱动表A中的每一条记录与被驱动表B的记录进行判断:

可以看到这种方式效率是非常低的,以上述表A数据100条,表B数据1000条计算,则A*B=10万次。开销统计如下。当然mysql肯定不会这么粗暴的去进行表的连接,所以就出现了后面的两种对Nested-Loop Join优化算法。

Index Nested-Loop Join (索引嵌套循环连接)

Index Nested-Loop Join其优化的思路主要是为了减少内存表数据的匹配次数,所以要求被驱动表上必须有索引才行。通过外层表匹配条件直接与内层表索引进行匹配,避免和内存表的每条记录去进行比较,这样极大的减少了对内存表的匹配次数。就是利用索引来提高匹配效率

 

驱动表中的每条记录通过被驱动表的索引进行访问,因为索引查询的成本是比较固定的,故mysql优化器都倾向于使用记录数少的表作为驱动表(外表)。如果被驱动表加索引,效率是非常高的,但如果索引不是主键索引,所以还得进行一次回表查询。相比,被驱动表的索引是主键索引,效率会更高。

 Block Nested-Loop Join(块嵌套循环连接)

 之前是将驱动表逐条与非驱动表的记录进行匹配,现在是引入join buffer缓冲区,将驱动表的记录缓冲到缓冲区,然后进行批量匹配,而不是逐条匹配。

Join小结

1、整体效率比较:INLJ > BNLJ > SNLJ

2、永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数量)(小的度量单位指的是表行数 * 每行大小)

select t1.b,t2.* from t1 straight_join t2 on (t1.b=t2.b) where t2.id<=100; # 推荐
select t1.b,t2.* from t2 straight_join t1 on (t1.b=t2.b) where t2.id<=100; # 不推荐

3、为被驱动表匹配的条件增加索引(减少内存表的循环匹配次数)

4、增大join buffer size的大小(一次索引的数据越多,那么内层包的扫描次数就越少)

5、减少驱动表不必要的字段查询(字段越少,join buffer所缓存的数据就越多

Hash Join

从MySQL的8.0.20版本开始将废弃BNLJ,因为从MySQL8.0.18版本开始就加入了hash join默认都会使用hash join

  • Nested Loop:

    对于被连接的数据子集较小的情况,Nested Loop是个较好的选择。

  • Hash Join是做大数据集连接时的常用方式,优化器使用两个表中较小(相对较小)的表利用Join Key在内存中建立散列表,然后扫描较大的表并探测散列表,找出与Hash表匹配的行。

    • 这种方式适合于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。

    • 在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要求有较大的临时段从而尽量提高I/O的性能。

    • 它能够很好的工作于没有索引的大表和并行查询的环境中,并提供最好的性能。大多数人都说它是Join的重型升降机。Hash Join只能应用于等值连接(如WHERE A.COL1 = B.COL2),这是由Hash的特点决定的。

 

小结

  • 保证被驱动表的JOIN字段已经创建了索引

  • 需要JOIN 的字段,数据类型保持绝对一致

  • LEFT JOIN 时,选择小表作为驱动表, 大表作为被驱动表 。减少外层循环的次数。

  • INNER JOIN 时,MySQL会自动将 小结果集的表选为驱动表 。选择相信MySQL优化策略。

  • 能够直接多表关联的尽量直接关联,不用子查询。(减少查询的趟数)

  • 不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用 JOIN 来代替子查询。

  • 衍生表建不了索引

相关文章:

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…...

数据结构第六节:二叉搜索树(BST)的基本操作与实现

【本节要点】 二叉搜索树&#xff08;BST&#xff09;基本原理代码实现核心操作实现辅助函数测试代码完整代码 一、二叉搜索树&#xff08;BST&#xff09;基本原理与设计总结 注&#xff1a;基本原理的详细分析可以在数据结构第六节中查看&#xff0c;这里是简单描述。 二叉搜…...

在昇腾GPU上部署DeepSeek大模型与OpenWebUI:从零到生产的完整指南

引言 随着国产AI芯片的快速发展&#xff0c;昇腾&#xff08;Ascend&#xff09;系列GPU凭借其高性能和兼容性&#xff0c;逐渐成为大模型部署的重要选择。本文将以昇腾300i为例&#xff0c;手把手教你如何部署DeepSeek大模型&#xff0c;并搭配OpenWebUI构建交互式界面。无论…...

在window终端创建docker容器的问题

问题&#xff1a; 错误原因&#xff1a; PowerShell 换行符错误 PowerShell 中换行应使用反引号而非反斜杠 \&#xff0c;错误的换行符导致命令解析中断。 在 Windows 的 PowerShell 中运行 Docker 命令时遇到「sudo 无法识别」的问题&#xff0c;这是因为 Windows 系统原生不…...

掌握Kubernetes Network Policy,构建安全的容器网络

在 Kubernetes 集群中&#xff0c;默认情况下&#xff0c;所有 Pod 之间都是可以相互通信的&#xff0c;这在某些场景下可能会带来安全隐患。为了实现更精细的网络访问控制&#xff0c;Kubernetes 提供了 Network Policy 机制。Network Policy 允许我们定义一组规则&#xff0c…...

ReAct论文阅读笔记总结

ReAct&#xff1a;Synergizing Reasoning and Acting in Language Models 背景 最近的研究结果暗示了在自主系统中结合语言推理与交互决策的可能性。 一方面&#xff0c;经过适当Prompt的大型语言模型&#xff08;LLMs&#xff09;已经展示了在算术、常识和符号推理任务中通…...

Linux云计算SRE-第十七周

1. 做三个节点的redis集群。 1、编辑redis节点node0(10.0.0.100)、node1(10.0.0.110)、node2(10.0.0.120)的安装脚本 [rootnode0 ~]# vim install_redis.sh#!/bin/bash # 指定脚本解释器为bashREDIS_VERSIONredis-7.2.7 # 定义Redis的版本号PASSWORD123456 # 设置Redis的访问…...

Python在数字货币交易中的算法设计:从策略到实践

Python在数字货币交易中的算法设计:从策略到实践 随着区块链技术的发展和加密货币市场的繁荣,数字货币交易已经成为金融领域的一个重要分支。从个体投资者到量化基金,算法交易(Algorithmic Trading)正在为提高交易效率和决策质量提供强大的支撑。在这些技术应用中,Pytho…...

高纬度、跨极区导航技术

本文是何昆鹏老师所写&#xff0c;在此非常感谢何老师的分享。 全球导航&#xff0c;特别是极区导航&#xff0c;一直被美俄导航领域所关注。美俄本身部分国土就处于极区&#xff0c;很多战略军事部署与全球航线也都处于该区域&#xff0c;加之其战略军事任务也都强调全球覆盖…...

用AI学编程2——python学习1

一个py文件&#xff0c;学会所有python所有语法和特性&#xff0c;给出注释&#xff0c;给出这样的文件 Python 学习整合文件 """ Python 学习整合文件 包含 Python 的基础语法、数据结构、函数定义、面向对象编程、异常处理、文件操作、高级特性等内容 每个部…...

用数据唤醒深度好眠,时序数据库 TDengine 助力安提思脑科学研究

在智能医疗与脑科学快速发展的今天&#xff0c;高效的数据处理能力已成为突破创新的关键。安提思专注于睡眠监测与神经调控&#xff0c;基于人工智能和边缘计算&#xff0c;实现从生理体征监测、智能干预到效果评估的闭环。面对海量生理数据的存储与实时计算需求&#xff0c;安…...

Ubuntu下MySQL的安装与使用(一)

目录 用户切换 MySQL的安装 MySQL的初步使用 登录与退出 Linux和mysql中的普通用户和root用户 查看、创建与使用 简单应用 MySQL 数据库在 Linux 文件系统中的存储结构 数据库、数据库服务、数据库管理系统&#xff08;宏观&#xff09; 微观下的DBMS SQL语言及其分…...

步进电机软件细分算法解析与实践指南

1. 步进电机细分技术概述 步进电机是一种将电脉冲信号转换为角位移的执行机构&#xff0c;其基本运动单位为步距角。传统步进电机的步距角通常为 1.8&#xff08;对应 200 步 / 转&#xff09;&#xff0c;但在高精度定位场景下&#xff0c;这种分辨率已无法满足需求。细分技术…...

pytorch retain_grad vs requires_grad

requires_grad大家都挺熟悉的&#xff0c;因此穿插在retain_grad的例子里进行捎带讲解就行。下面看一个代码片段&#xff1a; import torch# 创建一个标量 tensor&#xff0c;并开启梯度计算 x torch.tensor(2.0, requires_gradTrue)# 中间计算&#xff1a;y 依赖于 x&#x…...

RabbitMQ消息队列中间件安装部署教程(Windows)-2025最新版详细图文教程(附所需安装包)

目录 前言 一、安装Erlang环境 1、下载Erlang安装包 2、安装Erlang 3、设置环境变量 二、安装RabbitMQ环境 1、下载RabbitMQ安装包 2、安装RabbitMQ 3、设置环境变量 三、启动RabbitMQ 1、开启RabbitMQ管理插件 2、启动RabbitMQ 四、访问RabbitMQ 前言 RabbitMQ 是…...

vue-cli3+vue2+elementUI+avue升级到vite+vue3+elementPlus+avue总结

上一个新公司接手了一个vue-cli3vue2vue-router3.0elementUI2.15avue2.6的后台管理项目&#xff0c;因为vue2在2023年底已经不更新维护了&#xff0c;elementUI也只支持到vue2&#xff0c;然后总结了一下vue3的优势&#xff0c;最后批准升级成为了vitevue3vue-router4.5element…...

车载以太网测试-3【Wireshark介绍】

1 摘要 Wireshark 是一款开源的网络协议分析工具&#xff0c;广泛用于网络故障排查、协议分析、网络安全检测等领域。它能够捕获网络数据包&#xff0c;并以详细的、可读的格式显示这些数据包的内容。广泛应用于车载网络测试&#xff0c;是车载网络测试工程师必须掌握的工具。…...

扫雷雷雷雷雷雷雷

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 这一节课我们不学习新的知识&#xff0c;我们来做一个扫雷小游戏 目录 扫雷小游戏概述一、扫雷游戏分析…...

图片分类实战:食物分类问题(含半监督)

食物分类问题 simple_class 1. 导入必要的库和模块 import random import torch import torch.nn as nn import numpy as np import os from PIL import Image #读取图片数据 from torch.utils.data import Dataset, DataLoader from tqdm import tqdm from torchvision impo…...

RuoYi框架添加自己的模块(学生管理系统CRUD)

RuoYi框架添加自己的模块&#xff08;学生管理系统&#xff09; 框架顺利运行 首先肯定要顺利运行框架了&#xff0c;这个我不多说了 设计数据库表 在ry数据库中添加表tb_student 表字段如图所示 如图所示 注意id字段是自增的 注释部分是后面成功后前端要展示的部分 导入…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...