从源码看穿!MySQL 优化器是如何估算 SQL 语句的访问行数的?

news2024/11/13 13:00:52

全文目录:

    • 开篇语
    • 📖 前言
    • 🎯 目录
    • 🚀 为什么估算访问行数这么重要?
    • 🛠️ MySQL 优化器估算行数的原理概述
    • 🔍 统计信息:优化器的基础数据
    • 📈 行数估算的源码分析
      • 1️⃣ 获取统计信息
      • 2️⃣ 基于条件估算行数
      • 3️⃣ 索引选择
    • 🏗️ 实战案例:行数估算如何影响 SQL 性能
      • 优化器的行数估算流程
    • 🔄 延伸拓展:估算行数的挑战与改进思路
    • 🎉 结语
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

📖 前言

Hello,数据库界的伙伴们!你有没有想过,MySQL 是怎么知道某条 SQL 语句大概会访问多少行数据的?这种能力不仅是个“炫技”的小把戏,实际上关系到查询优化器如何选择执行计划,是数据库性能优化的关键一环!本篇文章,我们将深入 MySQL 的源码,看看 MySQL 的优化器到底是如何估算 SQL 语句的访问行数的。放心,这篇文章会用通俗易懂的方式,带你理解这块“神秘领域”的核心原理和实现细节。

在文章中,我们将逐步揭开统计信息、索引选择、代价模型、行数估算等关键点的实现原理,同时提供实战示例。无论你是刚接触数据库优化的小白,还是想要精通 MySQL 的开发老手,都能从这篇文章中收获满满的干货!


🎯 目录

  1. 🚀 为什么估算访问行数这么重要?
  2. 🛠️ MySQL 优化器估算行数的原理概述
  3. 🔍 统计信息:优化器的基础数据
  4. 📈 行数估算的源码分析
  5. 🏗️ 实战案例:行数估算如何影响 SQL 性能
  6. 🔄 延伸拓展:估算行数的挑战与改进思路
  7. 🎉 结语

🚀 为什么估算访问行数这么重要?

在 SQL 查询优化中,估算访问行数是最关键的任务之一。优化器在生成执行计划时,会尝试找出访问代价最低的方案,这个代价不仅包含扫描行数,还包含各种操作的 CPU 和 I/O 成本。对于同一张表的不同查询条件,如果行数估算偏差大,优化器很可能选择了效率不佳的计划,导致查询耗时剧增。

设想以下几种场景:

  • 条件扫描:假设我们查询一个庞大表中的少量数据。如果优化器高估了行数,可能会选择全表扫描;而如果低估了行数,又可能选择一个性能较差的索引。
  • 多表连接:在多表连接查询中,估算行数不仅决定了连接顺序,还会影响最终的连接代价。
  • 索引选择:MySQL 优化器会根据估算行数决定是否使用索引。如果误判了行数,可能会导致“不该用的索引被用上了”,反而影响查询性能。

因此,准确估算行数对于优化 SQL 执行性能至关重要!


🛠️ MySQL 优化器估算行数的原理概述

MySQL 优化器的行数估算,主要基于表的统计信息来完成。大致流程如下:

  1. 获取统计信息:优化器根据表的统计数据,如记录总数、索引分布、列的基数(distinct 值的数量)等,评估表的扫描代价。
  2. 基于条件的行数估算:对于带条件的 SQL 语句,优化器会结合统计信息估算符合条件的行数。例如,对于 WHERE age > 30 这种条件,优化器会参考 age 列的基数和分布情况,计算行数。
  3. 应用选择性公式:优化器使用选择性(selectivity)来估算行数。选择性是指一个条件过滤掉的数据比例,比如某个条件预计能筛掉 90% 的数据,那么选择性就是 10%。

这种基于统计信息的估算方法,可以避免全表扫描带来的时间开销,从而提高查询性能。


🔍 统计信息:优化器的基础数据

在行数估算中,统计信息是基础。MySQL 优化器会维护一系列统计信息,用于辅助行数估算。这些信息包括但不限于:

  • 表的行数:表中总记录数,这是行数估算的起点。
  • 列的基数(Cardinality):即某列的唯一值个数。高基数表示列的值分布很广,低基数表示分布很窄。
  • 索引选择性:用于评估某个索引是否合适。索引选择性越高,索引的过滤能力越强。
  • 直方图(Histogram):在一些数据库版本中,还会通过直方图记录列的分布信息,用于更精确地估算行数。

这些统计信息平时是自动更新的(例如 ANALYZE TABLE 命令会更新统计信息),优化器在查询过程中会实时使用这些统计信息。


📈 行数估算的源码分析

1️⃣ 获取统计信息

在源码中,MySQL 优化器会通过 TABLE_SHARE 结构体来获取表的基本信息。这其中包括表的行数(TABLE_SHARE::table_rows)和列基数(TABLE_SHARE::column_cardinality)。TABLE_SHARE 是一个保存表定义的结构体,优化器通过它获取统计信息。

longlong rows = share->table_rows;

2️⃣ 基于条件估算行数

接下来是条件的处理。在 SELECT_LEX::estimate_rowcount() 函数中,优化器会根据 WHERE 条件估算行数。这个过程首先根据条件中的列选择索引,再通过条件中的具体范围(如 >, <, BETWEEN 等)应用估算公式。

range_select() 函数为例:

double selectivity = ...; // 选择性估算
double estimated_rows = selectivity * rows;

这里,selectivity 通过条件筛选比例来计算,进一步估算出符合条件的行数。

3️⃣ 索引选择

choose_index() 函数会检查各索引的选择性,根据列的基数、索引的类型来判断。基数较高的列通常是优先选择的,因为它们能更好地筛选数据,降低扫描的行数。

if (index_cardinality > threshold) {
    use_index = true;
}

当满足选择条件时,优化器就会选择该索引,这也是优化器选择访问路径的关键步骤之一。


🏗️ 实战案例:行数估算如何影响 SQL 性能

假设我们有一张 employees 表,包含以下数据:

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    department VARCHAR(20)
);

数据总量为 10 万条,且 age 列有较高的基数。我们执行以下查询语句:

SELECT * FROM employees WHERE age > 40;

优化器的行数估算流程

  1. 获取统计信息:假设 age 列的基数为 5000,表行数为 100000。
  2. 选择性估算:假设 age > 40 筛选条件选择性为 0.4,即约有 40% 的数据满足条件。
  3. 行数估算:优化器会估算 100000 * 0.4 = 40000 行数据会被访问。

基于该行数估算,优化器会判断是使用索引扫描还是全表扫描。在这个例子中,如果 age 列上有索引,优化器可能会选择索引扫描;若无索引,可能会选择全表扫描。


🔄 延伸拓展:估算行数的挑战与改进思路

行数估算看似简单,实则有不少挑战,尤其是在复杂查询中。以下是一些常见挑战及改进方向:

  1. 统计信息不准确:统计信息不可能时时刻刻准确无误,尤其是数据频繁变更的表。对于这类表,可以通过定期 ANALYZE TABLE 或引入动态采样来改进。
  2. 联合条件估算:多个条件同时存在时,选择性估算会变得复杂。MySQL 目前采用简单的条件叠加方法,但对于复杂条件,机器学习模型可能更精准。
  3. 使用直方图:MySQL 8.0 中引入了直方图,通过记录更详细的分布信息,能够提高条件筛选的精确度,进而优化行数估算。

未来,MySQL 优化器也在逐步引入更加智能化的模型,以进一步提升估算精度。


🎉 结语

通过本篇文章,我们深入探讨了 MySQL 优化器是如何估算 SQL 语句的访问行数的。行数估算直接影响优化器选择执行计划,关乎 SQL 查询的性能表现。掌握这些细节,不仅有助于写出高效的 SQL 语

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器&#xff0c;将OpenCV中lib库里的o…

【含文档】基于ssm+jsp的校园疫情管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: apache tomcat 主要技术: Java,Spring,SpringMvc,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定义了两个…

在Django中安装、配置、使用CKEditor5,并将CKEditor5录入的文章展现出来,实现一个简单博客网站的功能

在Django中可以使用CKEditor4和CKEditor5两个版本&#xff0c;分别对应软件包django-ckeditor和django-ckeditor-5。原来使用的是CKEditor4&#xff0c;python manager.py makemigrations时总是提示CKEditor4有安全风险&#xff0c;建议升级到CKEditor5。故卸载了CKEditor4&…

网络管理之---3种网络模式配置

目标&#xff1a; 了解几个概念&#xff1a; 1.什么是IP&#xff1f;什么是IP地址&#xff1f; 2.什么是桥接、NAT、仅主机模式 3.端口&#xff1f; 4.什么是网络接口命名规则 5.网络管理器 IP&#xff1a;指网络之间互联的协议&#xff0c;是TCP/IP 体系中的网络协议 I…

统信UOS开发环境支持Electron

全面支持Electron开发环境,同时还提供了丰富的开发工具和开发资源,进一步提升工作效率。 文章目录 一、环境部署1. Electron应用开发介绍2. Electron开发环境安装安装Node.js和npm安装electron环境配置二、代码示例Electron开发案例三、常见问题一、环境部署 1. Electron应用…

三级等保安全解决方案,实施方案,整改方案(Word,PPT等相关资料学习)

信息系统进行三级等保的主要原因在于保障信息安全&#xff0c;维护国家安全和公共利益。三级等保是我国根据相关法律法规制定的信息安全等级保护制度中的一部分&#xff0c;旨在确保信息系统的完整性、可用性和保密性。通过三级等保&#xff0c;信息系统可以得到一系列的安全保…

优选算法合集————双指针(专题一)

题目一&#xff1a;移动零 题目描述&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输…

python基于深度学习的音乐推荐方法研究系统

需求设计 一款好的音乐推荐系统其目的是为用户进行合理的音乐推荐&#xff0c;普通的用户在登录到系统之后&#xff0c;能够通过搜索的方式获取与输入内容相关的音乐推荐&#xff0c;而以管理员登录到系统之后&#xff0c;则可以进行徐昂管的数据管理等内容操作。此次的需求主…

Docker 镜像和容器的导入导出及常用命令

Docker 镜像和容器的导入导出 1.1 镜像的导入导出 1.1.1 镜像的保存 通过镜像ID保存 方式一&#xff1a; docker save image_id > image-save.tar例如&#xff1a; rootUbuntu:/usr/local/docker/nginx# docker imagesREPOSITORY TAG IMAGE ID …

Java集合 List——针对实习面试

目录 Java集合 ListJava List的三种主要实现是什么&#xff1f;它们各自的特点是什么&#xff1f;Java List和Array&#xff08;数组&#xff09;的区别&#xff1f;Java List和Set有什么区别&#xff1f;ArrayList和Vector有什么区别&#xff1f;什么是LinkedList&#xff1f;…

超级干货O2OA数据中心-查询配置开发

O2OA提供的数据管理中心&#xff0c;可以让用户通过配置的形式完成对数据的汇总&#xff0c;统计和数据分组展现&#xff0c;查询和搜索数据形成列表数据展现。也支持用户配置独立的数据表来适应特殊的业务的数据存储需求。本文主要介绍如何在O2OA中开发和配置自定义数据查询语…

Unity中IK动画与布偶死亡动画切换的实现

在Unity游戏开发中&#xff0c;Inverse Kinematics&#xff08;IK&#xff09;是创建逼真角色动画的强大工具。同时&#xff0c;能够在适当的时候切换到布偶物理状态来实现死亡动画等效果&#xff0c;可以极大地增强游戏的视觉体验。本文将详细介绍如何在Unity中利用IK实现常规…

【ArcGISPro】单次将自己建立的工具箱添加至Arcpy中

新建工具箱 添加至Arcpy中 调用刚添加的工具箱

JVM的组成、字节码文件的组成

目录 java虚拟机的组成 字节码文件的组成 基础信息 常量池 字段 方法 属性 字节码相关的常用工具&#xff1a; 总结&#xff1a; 1、如何查看字节码文件&#xff1f; 2、字节码文件的核心组成有哪些&#xff1f; java虚拟机的组成 类加载器 ClassLoader运行时数据区…

新的服务器Centos7.6 安卓基础的环境配置(新服务器可直接粘贴使用配置)

常见的基础服务器配置之Centos命令 正常来说都是安装一个docker基本上很多问题都可以解决了&#xff0c;我基本上都是通过docker去管理一些容器如&#xff1a;mysql、redis、mongoDB等之类的镜像&#xff0c;还有一些中间件如kafka。下面就安装一个 docker 和 nginx 的相关配置…

Mysql COUNT() 函数详解

Mysql COUNT 函数详解 COUNT() 的几种用法COUNT(*)COUNT(1)COUNT(column)COUNT(*) 与 GROUP BYCOUNT(*) 与 GROUP BY 和 HAVING COUNT(expr) 的用法COUNT(DISTINCT expr)COUNT(expr) 带条件查询 写在最后 在使用Mysql的时候&#xff0c;作为开发者&#xff0c;聚合函数是肯定会…

yum下载时出现报错 Couldn‘t read a file:// file for file:///mnt/repodata/repomd.xml

得知说yum源指定的/mnt/没有镜像源 发现可能是镜像没有挂载成功 mount /dev/cdrom /mnt 清理一下缓存重新试一下 yum clean all yum install mod_ssl 解决

视觉SLAM数学基础

本文系统梳理从相机成像模型&#xff0c;通过不同图像帧之间的构造几何约束求解位姿变换&#xff0c;再根据位姿变换和匹配点还原三维坐标的过程&#xff0c;可以作为基于特征点法的视觉SLAM的数学基础。 1、相机成像模型 1.1、针孔相机模型 实际相机的成像方式通常很复杂&a…

书生大模型第四期闯关任务与笔记

书生大模型第四期闯关任务与笔记 入门岛第一关 Linux闯关任务&#xff1a;完成SSH连接与端口映射并运行hello_world.py笔记与过程SSH端口映射linux文件管理命令linux进程管理命令 第二关 Python闯关任务&#xff1a;Leetcode 383(笔记中提交代码与leetcode提交通过截图)闯关任务…

【React】深入理解 JSX语法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解 JSX语法1. JSX 简介2. JSX 的基本语法2.1 基本结构2.2 与普通 JavaScr…