MySQL连接查询解析与性能优化成本

文章目录

  • 一、连接查询
    • 1.连接查询基础
      • 1. INNER JOIN内连接
      • 2. LEFT JOIN (或 LEFT OUTER JOIN)左外连接
      • 3. RIGHT JOIN (或 RIGHT OUTER JOIN)右外连接
      • 4. FULL OUTER JOIN
    • 2.连接查询的两种过滤条件
    • 3.连接的原理
  • 二、性能优化成本
    • 1.基于成本的优化
    • 2.调节成本常数
      • (1)mysql.server_cost表
      • (2)mysql.engine_cost表

一、连接查询

1.连接查询基础

MySQL中的连接查询(JOIN)是用于从两个或多个表中检索数据的一种方法。当需要组合来自不同表的信息时,通常会使用连接查询。MySQL支持多种类型的JOIN,包括INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN等。

1. INNER JOIN内连接

INNER JOIN是最常用的连接类型,它返回两个表中满足连接条件的所有行。如果某一行在另一个表中没有匹配,则不会出现在结果集中。

示例:
假设我们有两个表,一个是employees(员工表),另一个是departments(部门表)。我们想要找出所有员工及其对应的部门名称。

SELECT employees.name, departments.department_name
FROM employees
INNER JOIN departments 
ON employees.department_id = departments.id;

2. LEFT JOIN (或 LEFT OUTER JOIN)左外连接

LEFT JOIN返回左表(FROM子句中提到的第一个表)中的所有记录,即使右表中没有匹配的记录。如果右表中没有匹配的记录,那么结果集中的对应列将包含NULL值。

示例:
如果我们想列出所有的员工以及他们所在的部门,即使有些员工还没有分配到任何部门,也可以使用LEFT JOIN。

SELECT employees.name, departments.department_name
FROM employees
LEFT JOIN departments 
ON employees.department_id = departments.id;

3. RIGHT JOIN (或 RIGHT OUTER JOIN)右外连接

RIGHT JOINLEFT JOIN相反,它返回右表中的所有记录,即使左表中没有匹配的记录。如果左表中没有匹配的记录,那么结果集中的对应列将包含NULL值。

示例:
如果我们想列出所有部门及其中的员工,即使有些部门目前没有员工,可以使用RIGHT JOIN。

SELECT employees.name, departments.department_name
FROM employees
RIGHT JOIN departments 
ON employees.department_id = departments.id;

4. FULL OUTER JOIN

FULL OUTER JOIN返回左表和右表中的所有记录。当某一行在其中一个表中没有匹配时,结果集中的对应列将包含NULL值。但是需要注意的是,MySQL本身并不直接支持FULL OUTER JOIN,可以通过UNION操作来模拟实现。

示例:
为了得到一个包含所有员工和部门的列表,无论是否有对应的匹配项,可以这样做:

SELECT employees.name, departments.department_name
FROM employees
LEFT JOIN departments 
ON employees.department_id = departments.id
UNION
SELECT employees.name, departments.department_name
FROM employees
RIGHT JOIN departments 
ON employees.department_id = departments.id;
  • 在使用JOIN时,确保连接条件是正确的,以避免产生过多的笛卡尔积(即每个表的每一行都与其他表的每一行配对)。
  • 当处理大型数据集时,考虑使用索引来提高性能。
  • 对于复杂的查询,可能需要使用子查询、视图或其他高级技术来优化性能和可读性。

2.连接查询的两种过滤条件

  • WHERE子句中的过滤条件:

WHERE子句中的过滤条件就是我们平时见的那种,不论是内连接还是外连接,凡是不符合WHERE子句中的过滤条件的记录都不会被加入最后的结果集。

  • ON子句中的过滤条件:

对于外连接的驱动表(即,left join中左边的表,或right join中右边的表)的记录来说,如果无法在被驱动表中找到匹配ON子句中的过滤条件的记录,那么该记录仍然会被加入到结果集中,对应的被驱动表记录的各个字段使用NULL值填充。

如果把ON子句放到内连接中,MySQL会把它和WHERE子句一样对待。

一般情况下,我们都把只涉及单表的过滤条件放到WHERE子句中,把涉及两表的过滤条件都放到ON子句中。

3.连接的原理

在执行连接查询语句时,大致会经历以下两个步骤:

  • 步骤1:选取驱动表,使用与驱动表相关的过滤条件,选取代价最低的单表访问方法来执行对驱动表的单表查询。

  • 步骤2:对上一步骤中查询驱动表得到的结果集中每一条记录,都分别到被驱动表中查找匹配的记录。

驱动表只访问一次(步骤1),但被驱动表却可能被多次访问(步骤2)。无论是步骤1还是步骤2都可以利用索引来加快查询速度。

二、性能优化成本

相信大家都经常听说数据库优化这词,所以,数据库的优化是针对什么进行优化呢?这就不得不提到MySQL的优化成本了:

  • I/O成本:

我们的表经常使用的MyISAM、InnoDB存储引擎都是将数据和索引都存储到磁盘上的,当我们想查询表中的记录时,需要先把数据或者索引加载到内存中然后再操作。这个从磁盘到内存这个加载的过程损耗的时间称之为I/O成本。

  • CPU成本:

读取以及检测记录是否满足对应的搜索条件、对结果集进行排序等这些操作损耗的时间称之为CPU成本。

对于InnoDB存储引擎来说,页是磁盘和内存之间交互的基本单位,MySQL的设计者规定读取一个页面花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默认是0.2。1.0、0.2这些数字称之为成本常数。

1.基于成本的优化

在MySQL中,性能优化都是花费尽可能少的成本来达到检索目标的,大致是这么一个过程:

  • 根据搜索条件,找出所有可能使用的索引;
  • 计算全表扫描的代价;
  • 计算使用不同索引执行查询的代价;
  • 对比各种执行方案的代价,找出成本最低的那一个。

2.调节成本常数

MySQL将成本常数存储到了mysql数据库(系统数据库)中的两个表中,一个叫engine_cost,存储的是存储引擎的成本常数;另一个叫server_cost,存储的是MySQL server端的成本常数。

在server层进行连接管理、查询缓存、语法解析、查询优化等操作,在存储引擎层执行具体的数据存取操作。也就是说一条语句在server层中执行的成本是和它操作的表使用的存储引擎是没关系的,所以关于这些操作对应的成本常数就存储在了server_cost表中,而依赖于存储引擎的一些操作对应的成本常数就存储在了engine_cost表中。

(1)mysql.server_cost表

server_cost表中在server层进行的一些操作对应的成本常数,具体内容如下:

在这里插入图片描述

  • 列的说明:

    • cost_name:表示成本常数的名称。
    • cost_value:表示成本常数对应的值。如果该列的值为NULL的话,意味着对应的成本常数会采用默认值。
    • last_update:表示最后更新记录的时间。
    • comment:注释。
  • 成本常量说明:

  • disk_temptable_create_cost:默认值是40.0,创建基于磁盘的临时表的成本,如果增大这个值的话会让优化器尽量少的创建基于磁盘的临时表。

  • disk_temptable_row_cost:默认值是1.0,向基于磁盘的临时表写入或读取一条记录的成本,如果增大这个值的话会让优化器尽量少的创建基于磁盘的临时表。

  • key_compare_cost:默认值是0.1,两条记录做比较操作的成本,多用在排序操作上,如果增大这个值的话会提升filesort的成本,让优化器可能更倾向于使用索引完成排序而不是filesort。

在MySQL中,FileSort 是一个排序算法,用于处理那些无法通过索引直接完成排序的查询。当MySQL执行一个查询并需要根据某些字段对结果进行排序时,如果这些字段上没有合适的索引,或者查询的复杂度导致MySQL决定不使用现有索引,MySQL就会使用 FileSort 方法来对结果集进行排序。
算法一——内存排序:MySQL首先尝试在内存中对数据进行排序。如果排序的数据量较小,可以完全放入内存中,MySQL会在内存中完成排序操作。MySQL使用一个称为“sort buffer”的内存区域来存储待排序的数据。
算法二——磁盘排序:如果数据量过大,超出了可用的内存大小,MySQL会将部分数据写入临时文件,并在磁盘上进行排序。这种情况下,MySQL会创建多个临时文件,每个文件中包含一部分排序后的数据。最后,MySQL会将这些临时文件合并成一个最终的排序结果。
识别FileSort:在执行 EXPLAIN 命令时,如果看到 Extra 列中有 Using filesort,这表明MySQL正在使用 FileSort 来对结果集进行排序。

  • memory_temptable_create_cost :默认2.0,创建基于内存的临时表的成本,如果增大这个值的话会让优化器尽量少的创建基于内存的临时表。
  • memory_temptable_row_cost:默认0.2,向基于内存的临时表写入或读取一条记录的成本,如果增大这个值的话会让优化器尽量少的创建基于内存的临时表。
  • row_evaluate_cost:默认0.2,检测一条记录是否符合搜索条件的成本,增大这个值可能让优化器更倾向于使用索引而不是直接全表扫描。

MySQL在执行诸如DISTINCT查询、分组查询、Union查询以及某些特殊条件下的排序查询都可能在内部先创建一个临时表,使用这个临时表来辅助完成查询(比如对于DISTINCT查询可以建一个带有UNIQUE索引的临时表,直接把需要去重的记录插入到这个临时表中,插入完成之后的记录就是结果集了)。在数据量大的情况下可能创建基于磁盘的临时表,也就是为该临时表使用MyISAM、InnoDB等存储引擎,在数据量不大时可能创建基于内存的临时表,也就是使用Memory存储引擎。

(2)mysql.engine_cost表

在这里插入图片描述

  • engine_name列:指成本常数适用的存储引擎名称。如果该值为default,意味着对应的成本常数适用于所有的存储引擎。

  • device_type列:指存储引擎使用的设备类型,这主要是为了区分常规的机械硬盘和固态硬盘,不过在MySQL 5.7.21这个版本中并没有对机械硬盘的成本和固态硬盘的成本作区分,所以该值默认是0。

  • 成本常量说明:

io_block_read_cost:默认值1.0,从磁盘上读取一个块对应的成本。对于InnoDB存储引擎来说,一个页就是一个块,不过对于MyISAM存储引擎来说,默认是以4096字节作为一个块的。增大这个值会加重I/O成本,可能让优化器更倾向于选择使用索引执行查询而不是执行全表扫描。
memory_block_read_cost:默认值1.0,与上一个参数类似,只不过衡量的是从内存中读取一个块对应的成本。

当我们想要通过调整成本常量值来优化MySQL性能时,可以根据业务需求来调整mysql.engine_cost和mysql.server_cost中的成本常量值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在Markdown写文章上传到wordpress保证图片不丢失

如何在Markdown写文章上传到wordpress保证图片不丢失 写文日期,2023-11-16 引文 众所周知markdown是一款nb的笔记软件,本篇文章讲解如何在markdown编写文件后上传至wordpress论坛。并且保证图片不丢失(将图片上传至云端而非本地方法) 一&…

WSL进阶体验:gnome-terminal启动指南与中文显示问题一网打尽

起因 我们都知道 wsl 启动后就死一个纯命令行终端,一直以来我都是使用纯命令行工具管理Linux的。今天看到网上有人在 wsl 中启动带图形界面的软件。没错,就是在wsl中启动带有图形界面的Linux软件。比如下面这个编辑器。 ​​ 出于好奇,我就…

Linux部署python web项目Flask + gunicorn + nginx

文章目录 一、安装python&使用虚拟环境二、python程序重要参数加密2.1 非对称加密(RSA)2.2 生成密钥对2.4 以连接数据库参数加密为例2.4.1 工具类RSA.py 三、一个简单的Flask项目四、安装配置gunicorn4.1 安装4.2 启动/配置(选择eventlet)4.2.1 命令…

vue打包exe之electron-quick-start的npm install 报错

vue打包exe之electron-quick-start的npm install 报错 1、github地址2、问题3、解决4、其他(打包exe)参考 1、github地址 https://github.com/electron/electron-quick-start2、问题 我使用的pnpm install正常安装,执行npm start提示错误 3、解决 在package.js…

【LLM多模态】文生视频综述From Sora What We Can See: A Survey of Text-to-Video Generation

note 现在很多主流的文生视频应该还是Diffusion-based 基于扩散模型的方法这篇综述将现有研究按照三个维度进行分类:进化生成器(Evolutionary Generators)、卓越追求(Excellent Pursuit)、现实全景(Realis…

【学习笔记】MIPI

MIPI介绍 MIPI是由ARM、Nokia、ST、IT等公司成立的一个联盟,旨在把手机内部的接口如存储接口,显示接口,射频/基带接口等标准化,减少兼容性问题并简化设计。 MIPI联盟通过不同的工作组,分别定义一系列手机内部的接口标…

植物大战僵尸杂交版V2.5.1下载(最新版)

2.5.1版本更新公告: 在最新的2.5.1版本中,游戏对“两面夹击”关卡进行了多项重要调整。出怪倍率和种类均有所降低,部分关卡的初始阳光量也得到了调整,以增强玩家的策略性。同时,玩家可以在这些关卡中使用投手类植物&a…

sysbench 命令:跨平台的基准测试工具

一、命令简介 sysbench 是一个跨平台的基准测试工具,用于评估系统性能,包括 CPU、内存、文件 I/O、数据库等性能。 ‍ 比较同类测试工具 bench.sh 在上文 bench.sh:Linux 服务器基准测试中介绍了 bench.sh 一键测试脚本,它对…

RabbitMQ下载安装运行环境搭建

RabbitMQ运行环境搭建 1、Erlang及RabbitMQ安装版本的选择2、下载安装Erlang2.1、下载Erlang2.2、安装Erlang2.2.1、安装Erlang前先安装Linux依赖库2.2.2、解压Erlang压缩包文件2.2.3、配置2.2.4、编译2.2.5、安装2.2.6、验证erlang是否安装成功 3、RabbitMQ下载安装3.1、下载3…

FortiGate 无线组网

无线管理与配置 FortiAP 连接 internal 接口之后自动获得 ip 地址:192.168.1.xxx/24在 FortiGate 中创建 SSIDFortiGate 自动发现 FortiAP,将 FortiAP 添加到 FortiGate将 SSID 和 FortiAP 关联创建防火墙策略 下面我们就来一起看看在 FortiGate 中该如…

MT6765/MT6762(R/D/M)/MT6761(MT8766)安卓核心板参数比较_MTK联发科4G智能模块

联发科Helio P35 MT6765安卓核心板 MediaTek Helio P35 MT6765是智能手机的主流ARM SoC,于2018年末推出。它在两个集群中集成了8个ARM Cortex-A53内核(big.LITTLE)。四个性能内核的频率高达2.3GHz。集成显卡为PowerVR GE8320,频率…

前端——js基础

一、JavaScript (简称js)——js可以给网页实现一个动态效果 1.JavaScript 组成 - 核心语法 ECMScipt 简称(es): 规范js的基本语法 1.es是js的语法规范 管理者 2.js是es的实现 操作者 - DOM > 文档对象 提供js操作 (例如…

Golang | Leetcode Golang题解之第423题从英文中重建数字

题目: 题解: func originalDigits(s string) string {c : map[rune]int{}for _, ch : range s {c[ch]}cnt : [10]int{}cnt[0] c[z]cnt[2] c[w]cnt[4] c[u]cnt[6] c[x]cnt[8] c[g]cnt[3] c[h] - cnt[8]cnt[5] c[f] - cnt[4]cnt[7] c[s] - cnt[6]…

jq实现:点击图片时弹出详情弹窗,判断拖动图片时不弹出

1.需求分析: 要实现点击图片时弹出详情弹窗,但在拖动时不弹出,可以使用 jQuery 来判断用户的操作。可以通过设置一个标志变量来判断用户是否在拖动图片。 并且在鼠标拖动某个图片时将其层级设置为最上面,可以使用 jQuery 结合 CSS 的 z-index 属性 说明 : 标志变量:使用…

传输层TCP协议

一、TCP协议格式 我们看到报头固定有20字节,最后选项大小不固定。 4位首部长度(二进制0000 ~ 1111,十进制范围[0, 15])单位是4字节(存放字节大小范围[0, 60])包括了20字节固定长度 选项长度。若选项大小为…

PWA(Progressive web APPs,渐进式 Web 应用): manifest.json、 Service Worker

文章目录 引言I 什么是 PWA功能特性技术上分为三个部分:II Web 应用清单将Web 应用清单文件链接到站点manifest.json字段说明III Service WorkerService worker 本质Service worker 运行在 worker 上下文注册服务辅助角色扩展知识将 PWA 作为脱机应用定义当前文档与被链接文档…

用Python实现运筹学——Day 4: 线性规划的几何表示

一、学习内容 线性规划的几何表示: 线性规划问题的解通常位于一个凸多边形(即可行解空间)的顶点上,这意味着在求解线性规划问题时,只需要找到可行解空间中的顶点并计算出目标函数值,再选择其中的最优解。 可…

C++之分割字符串的两种方式

方式一 #include <string> #include <vector> #include <sstream> #include <iostream>std::vector<std::string> split(const std::string& str, char delim) {std::stringstream ss(str);std::string item;std::vector<std::string>…

C语言贪吃蛇小游戏演示和说明

C语言贪吃蛇小游戏演示和说明 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础&#xff0c;训练编程思维&#xff0c;培养解决问题的思路&#xff0c;领略多姿多彩的C语言。 游戏开始后&#xff0c;会在中间位置出现一条只有三个节点的贪吃蛇&#xff0c;并随机出现一个食物&am…

keepalived+lvs集群,实现高可用

环境准备&#xff1a;两台虚拟机&#xff0c;关闭防火墙&#xff0c;selinux,配置阿里云仓库&#xff0c;配置epel 192.168.88.21 dr1 负载均衡器 master 192.168.88.22 dr2 负载均衡器 backup 192.168.88.23 rs1 web1 192.168.88.24 rs2 web2 实验说明&…