结合数据索引结构看SQL的真实执行过程

news2024/11/26 18:34:12

引言

关于数据库设计与优化的前几篇文章中,我们提到了数据库设计优化应该遵守的指导原则、数据库底层的索引组织结构、数据库的核心功能组件以及SQL的解析、编译等。这些其实都是在为SQL的优化、执行的理解打基础。
今天这篇文章,我们以MySQL中InnoDB存储引擎中的数据索引组织及一条SQL的物理执行过程,来更直观的理解数据库中我们提交一条SQL后,数据库默默帮我们做的事情。

准备工作

我们依然以前一篇文章中的t_customer表为例,建表语句如下:

create table t_customer(
  id int not null auto_increment comment '会员id',
  name varchar(32) comment '会员姓名',
  gender tinyint not null default 0 comment '会员性别:0未知,1男,2女',
  city varchar(32) comment '会员所在城市',
  primary key(`id`),
  key `idx_city` (`city`)
) comment '会员信息表';

然后我们编写一个Python脚本,利用Faker框架,来生成测试数据:

import random
from faker import Faker
from faker.providers import BaseProvider
import pymysql
import db_config as db_cfg

print(db_cfg.host)

conn = pymysql.connect(host=db_cfg.host, port=db_cfg.port, user=db_cfg.user, password=db_cfg.password,
                       database=db_cfg.database)
cursor = conn.cursor()
sql = "insert into t_customer(name, gender, city) values('{}', {}, '{}')"


class GenderProvider(BaseProvider):
    def gender(self):
        return random.sample([1, 2, 0], counts=[100, 100, 1], k=1)[0]


# 指定语言环境为中文环境,创建Faker生成器
fk = Faker('zh_CN')
fk.add_provider(GenderProvider)
for i in range(10000):
    cursor.execute(sql.format(fk.name(), fk.gender(), fk.city()))
conn.commit()
cursor.close()
conn.close()

测试数据大概如下:

其实这里我们只是从数据组织结构上展开SQL的执行,没有测试数据也没啥影响。不过,还是强烈建议感兴趣的了解下Python,很好用,很好玩。这里不再展开,需要理解的可以看下笔者关于Python的相关系列文章。

B+树的索引组织结构

简单说下B+树索引

B+树索引,就是传统意义上的索引,也是目前关系型数据库系统中查找最为常用和最有效的索引。
需要注意的是,从使用的角度来看,B+树索引的构造类似于二叉树,根据键值(key value)能够快速找到相应的数据。但是,有几个细节需要提一下:

  • B+树中的B不是表示二叉(binary),而是代表平衡(balance),因为B+树是从最早的平衡二叉树演化而来的,但是B+树不是一个二叉树
  • 树结构的索引,只有是平衡树,才能降低树的高度,从而降低基于索引检索的磁盘IO的次数
  • B+树索引,实际上并不能通过一个给定的键值查到具体的某一行数据,而是只能找到被查找符合键值的数据所在的页,这些数据按照键值顺序进行组织存储。然后数据库通过把页读入内存,然后在内存中执行进一步的查找操作,最终得到要查找的数据。后续我们简化一下操作,假设每个页都只存储一条数据,以便更好地进行表述、理解
  • 关于数据以页为单位进行读取,前面的文章中已经提到,可以更好地利用程序的局部性原理,从而提高检索的效率
t_customer的索引结构

引言中已经提到,我们这里以MySQL的InnoDB存储引擎为例进行介绍,其他数据库中的底层原理也基本类似。
从前面的建表语句中,可以看出t_customer有两个索引:

  • 主键索引 id,是聚簇索引(Clustered Index)
  • idx_city,是辅助索引(Secondary Index)

索引的示意图大概如下:

前面已经提到,我们简化一下,一个页只存储一条数据。
辅助索引的叶子结点,存储的都是该索引的键值及对应的主键的值;
聚簇索引的叶子节点,存储的都是一行行完整的数据。

SQL执行过程

接下来,我们将要执行的是这样一条SQL语句:

select 
  id,name 
from 
  t_customer 
where 
  city = '合肥' 
  and gender = 1

假设数据库的优化器最终决定要走idx_city这个索引,进行SQL的执行,主要的执行过程大概如下:

  • 从索引idx_city中找到第一个满足city = '合肥'的主键id;
  • 到主键id索引中取出整行,将id, name, gender取出,如果gender = 1 则将id, name的值放入内存缓冲区;
  • 重复前两个步骤,直到在idx_city索引中找到的city值不满足查询条件为止
  • 将内存缓冲区的数据返回给用户

上面的这条SQL,首先从idx_city索引中找到主键id,然后再到聚簇索引中找到整行记录,然后还要判断是否符合条件,再决定是否返回改行数据。这种查询场景,叫做”回表“。
回表的操作,会增加磁盘IO的次数,如果辅助索引结构中已经包含了用户需要的所有字段,则可以避免回表的操作,这时候的索引叫做”覆盖索引“。

下面,我们对这条SQL稍微修改一下:

select 
  id,name 
from 
  t_customer 
where 
  city = '合肥' 
  and gender = 1
order by
  name 
limit 100

现在这条要执行的SQL中,添加了排序及limit操作,执行的过程会发生相应的调整,假设优化器还是选择了要走idx_city这个索引:

  • 从索引idx_city中找到第一个满足city = '合肥'的主键id;
  • 到主键id索引中取出整行,将id, name, gender取出,如果gender = 1 则将id, name的值放入排序缓冲区sor_buffer中;
  • 重复前两个步骤,直到在idx_city索引中找到的city值不满足查询条件为止
  • 对sort_buffer中的数据按照字段name进行快速排序;
  • 按照排序结果的数据取出前100条,返回给用户

其实,涉及到排序的话,问题会突然变得复杂起来,这里简单描述下,可能的情况:
1、符合条件的行数很多,sort_buffer中放不下,这时候就不能直接基于内存的排序算法进行了,就需要我们前面文章提到的TPMMS的算法了,进行基于磁盘的多路归并排序;
2、加入最终返回的字段比较多,执行引擎在执行的过程中,可能决定不将所有字段都放入sort_buffer,可能只放主键id和参与排序的字段,然后排序完成之后,需要再按序进行一次回表的操作,获取用户需要的所有字段,然后再返回给用户。基于是否将所有字段放入sort_buffer中,排序的操作符可以简单分为全字段排序和rowid排序。

实际上SQL的执行要考虑的真实场景比较复杂,本文为了便于描述与理解,做了相应的简化,感兴趣的可以自行研究。

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

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

相关文章

【Cadence18】如何放置定位孔

在菜单的place->manually会出现Placement对话框, 在Advanced settings中勾选database和library 然后点击Placement list,下拉框中选择Mechanical symbols,勾选你要的定位孔 (如下图的HOLE_1_6R00D2R70-PTH,注意:…

Windows 11内置一键系统备份与还原 轻松替代Ghost

面对系统崩溃、恶意软件侵袭或其他不可预见因素导致的启动失败,Windows 7~Windows 11内置的系统映像功能能够迅速将您的系统恢复至健康状态,确保工作的连续性和数据的完整性。 Windows内置3种备份策略 U盘备份:便携且安全 打开“创建一个恢…

平替向日葵:Windows远程桌面+动态IP获取器

对于需要远程办公的人员来说,向日葵是一个操作简便的选择,但其免费版功能受限,且由于数据需经过向日葵服务器转发,安全性也无法得到完全保障。为此,以下提供一个更为简单且免费的替代方案: 使用Windows自带…

一则 MySQL 子查询改写 SQL 优化小案例

一篇短小精悍的 SQL 优化案例! 作者:马文斌,MySQL/Redis 爱好者~ 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。 本文约 600 字,预计阅读需要 2 分钟。 事情是这样的 近日…

CobaltStrike的内网安全

1.上线机器的Beacon的常用命令 2.信息收集和网站克隆 3.钓鱼邮件 4.CS传递会话到MSF 5.MSF会话传递到CS 1上线机器的Beacon的常用命令 介绍:CobaltStrike分为服务端和客户端,一般我们将服务端放在kali,客户端可以在物理机上面&#xff0…

React 19 竞态问题解决

竞态问题/竞态条件 指的是,当我们在交互过程中,由于各种原因导致同一个接口短时间之内连续发送请求,后发送的请求有可能先得到请求结果,从而导致数据渲染出现预期之外的错误。 因为防止重复执行可以有效的解决竞态问题&#xff0…

ChatGPT:SpringBoot解决跨域问题方法-手动设置请求头

ChatGPT:SpringBoot解决跨域问题方法-手动设置请求头 这里的设置响应头是为了发送请求方还是接收请求方 设置响应头是为了发送请求方。具体来说,添加 Access-Control-Allow-Origin 头部是为了告诉浏览器,哪些域名可以访问资源。当设置为 * 时…

鼠标自动点击器怎么用?鼠标连点器入门教程!

鼠标自动点击器是适用于Windows电脑的自动执行鼠标点击操作的工具,主要用于模拟鼠标点击操作,实现鼠标高速点击的操作。通过模拟鼠标点击,可以在用户设定的位置、频率和次数下自动执行点击动作。 鼠标自动点击器主要的应用场景: …

使用工业自动化的功能块实现大语言模型应用

大语言模型无所不能? 以chatGPT为代表的大语言模型横空出世,在世界范围内掀起了一场AI革命。给人的感觉似乎大模型语言无所不能。它不仅能够生成文章,图片和视频,能够翻译文章,分析科学和医疗数据,甚至可以…

矩阵键盘与密码锁

目录 1.矩阵键盘介绍​编辑 2.扫描的概念 3.代码演示(读取矩阵键盘键码) 4.矩阵键盘密码锁 1.矩阵键盘介绍 为了减少I/O口的占用,通常将按键排列成矩阵形式,采用逐行或逐列的 “扫描”,就可以读出任何位置按键的状态…

C++ 视觉开发 六.特征值匹配

以图片识别匹配的案例来分析特征值检测与匹配方法。 目录 一.感知哈希算法(Perceptual Hash Algorithm) 二.特征值检测步骤 1.减小尺寸 2.简化色彩 3.计算像素点均值 4.构造感知哈希位信息 5.构造一维感知哈希值 三.实现程序 1.感知哈希值计算函数 2.计算距离函数 3…

Transformer和Mamba强强结合!最新混合架构全面开源,推理速度狂飙8倍

最近发现,将Mamba和Transformer模块混合使用,效果会比单独使用好很多,这是因为该方法结合了Mamba的长序列处理能力和Transformer的建模能力,可以显著提升计算效率和模型性能。 典型案例如大名鼎鼎的Jamba:Jamba利用Tr…

自定义流程表单开发优势体现在什么地方?

提质、增效、降本,应该是很多职场办公需要实现的发展目标。那么,应用什么样的软件平台可以实现?低代码技术平台、自定义流程表单开发是目前流行于职场行业中的软件产品,可视化操作界面、够灵活、易维护等优势特点明显,…

考到PMP证书后 如何获得PDU?

目前仅续证一次,也是在威班PMP考试后免费积攒的。其实获取PMP的渠道很多,网上也有很多售卖的,积攒起来也挺容易,不过在续证的时候千万不要找不明渠道来源的人去搞,不靠谱。续证期有三年的,三年时间积攒60PD…

理解机器学习中的潜在空间(Understanding Latent Space in Machine Learning)

1、什么是潜在空间? If I have to describe latent space in one sentence, it simply means a representation of compressed data. 如果我必须用一句话来描述潜在空间,它只是意味着压缩数据的表示。 想象一个像上面所示的手写数字(0-9&…

天猫超市卡怎么用

猫超卡是在天猫超市里面消费用的卡 但是我们现在买东西都喜欢货比三家,肯定是哪家划算在哪买,要是淘宝其他店铺或京东卖的更便宜,猫超卡自然就用不上了 这种情况的话,还不如直接把猫超卡的余额提出来,买东西也不受限…

RPMBUILD从入门到放弃

前言 为什么会产生这篇文章?促使我写出这片文章的背景是:前几周出差至客户现场部署服务,由于客户是zf,底层物理机都是浪潮品牌,且内网涉密。由于没有提前告知此情况,我误以为还是之前的安装方式一套流程就能部署完成,但没想到的是中间件的安…

Pandas 入门 15 题

Pandas 入门 15 题 1. 相关知识点1.1 修改DataFrame列名1.2 获取行列数1.3 显示前n行1.4 条件数据选取值1.5 创建新列1.6 删去重复的行1.7 删除空值的数据1.9 修改列名1.10 修改数据类型1.11 填充缺失值1.12 数据上下合并1.13 pivot_table透视表的使用1.14 melt透视表的使用1.1…

精准调整:数控切割机导轨的水平与垂直度校准!

滚柱导轨因其具有高承载、高精度、高稳定性和长寿命等特点,被广泛应用在重型设备、精密设备、自动化生产线、航空航天和半导体设备等领域。尤其是在数控切割机中的应用,最为广泛。 对于数控切割机来说,滚柱导轨的调整非常重要,是数…

在 Baklib Experience 中实现混合 CMS 架构

“还记得 CMS 主要用于在网页上布局内容吗?当时,这满足了网站管理需求。然而,行业正在发生变化,数字体验平台 Baklib Digital Content Experience 正在引领潮流。继续阅读以了解如何以及详细了解可用于确保全渠道成功的两个原则。…