本文是 MySQL 简单查询语句执行过程分析
6 篇中的第 2 篇,第 1 篇请看这里:
[MySQL 简单查询语句执行过程分析(一)词法分析 & 语法分析]
这一篇主要讲的内容是一条简单查询语句,在查询准备阶段
会干哪些事情?分 3 个部分:
示例表及 SQL 如下:
-- 表结构
CREATE TABLE `t_recbuf` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`i1` int(10) unsigned DEFAULT '0',
`str1` varchar(32) DEFAULT '',
`str2` varchar(255) DEFAULT '',
`c1` char(11) DEFAULT '',
`e1` enum('北京','上海','广州','深圳','天津','杭州','成都','重庆','苏州','南京','洽尔滨','沈阳','长春','厦门','福州','南昌','泉州','德清','长沙','武汉') DEFAULT '北京',
`s1` set('吃','喝','玩','乐','衣','食','住','行','前后','左右','上下','里外','远近','长短','黑白','水星','金星','地球','火星','木星','土星','天王星','海王星','冥王星') DEFAULT '',
`bit1` bit(8) DEFAULT b'0',
`bit2` bit(17) DEFAULT b'0',
`blob1` blob,
`d1` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2001 DEFAULT CHARSET=utf8;
-- 查询语句
select * from t_recbuf where i1 > 49276
接下来,我们进入正题,展开讲讲这 3 部分内容。
从存储引擎读取数据之前,MySQL 需要把 SQL 中涉及的所有表的信息读取出来。研究源码之前,我想象中的打开表
就是读取 frm 文件中的信息,构造出来一个对象啥的,然后就没有然后了,不知道正在看文章的你想象中的打开表的过程
是什么样的呢?
MySQL 打开表的过程比较复杂,读取 frm 文件并进行处理的一个方法就有 1700+ 行代码,还不包括调用的其它方法。
正是因为打开表的过程复杂,而代码复杂意味着执行效率下降,这对于 MySQL 来说是不能接受的,所以必定要有优化手段。
每次执行 SQL 的时候,不管是增、删、改、查,还是修改表结构,都要打开表,可见打开表是个非常频繁的操作,对于这种复杂而又频繁的操作,能用什么优化手段呢?聪明如你,一定能够想到,当然是用缓存
了。
没错,MySQL 中就是用缓存的思想实现的,而且是本机内存缓存,效率极高。天下武功,唯快不破,为了快的极致,MySQL 还不只用了一级缓存,而是用了两级缓存。
一级缓存
一级缓存是TABLE 类实例缓存
,顾名思义,该缓存中保存的就是已经创建好的 TABLE
类实例,是之前的连接中使用过的 TABLE 类实例,用完之后又放回到缓存中了,所以从这个缓存里拿到的 TABLE 类实例,可以直接使用。打开表时,第一步就是从这个缓存中去拿 TABLE 类实例
。
TABLE 类实例中保存的是表结构信息。
从缓存中查找 TABLE 类实例,需要一个 key,这个 key 是由数据库名和表名组成的,key 的形式是 dbname_tablename
。
TABLE 类实例缓存
实际上并不是只有 1 个,而是有多个,数量由系统变量 table_open_cache_instances
控制,默认为 16
。总共可以缓存多少个实例由系统变量 table_open_cache
控制,默认为 2000
,所以默认情况下,每个 TABLE 类实例缓存
可以缓存 2000 / 16 = 125 个 TABLE 类实例。
同一个表的 TABLE 类实例,在缓存中可以存在很多个,理论上限是 table_open_cache
,就是缓存的全都是同一个表的 TABLE 类实例。
那么,怎么确定要从哪个
TABLE 类实例缓存
读取 TABLE 类实例呢?是这样的:每个连接都会有一个线程 ID
,用线程 ID % table_open_cache_instances
得到一个序号,通过序号
找到对应的TABLE 类实例缓存
。
既然是缓存,就会涉及到缓存满了怎么办的问题,对于 TABLE 类实例缓存
,当往缓存中放入 TABLE 类实例时,会判断缓存是否已满,如果满了,则按照最近最少使用原则,把多出来的 TABLE 类实例释放掉。还有另一种方式就是手动了,执行 FLUSH TABLES
命令可以清空缓存。
如果从一级缓存中没有读取到 TABLE 类实例,就要进入二级缓存
的处理流程了,二级缓存逻辑比一级缓存复杂,所以执行效率要低一些。
二级缓存
二级缓存是 TABLE_SHARE 类实例缓存
,可以缓存的 TABLE_SHARE 类实例数量由系统变量 table_definition_cache
控制,默认为 1400
,每个表只对应一个
TABLE_SHARE 实例,从这个缓存中读取到 TABLE_SHARE 类实例以后,用该实例中的各个属性去创建并初始化一个 TABLE 类实例,然后就可以使用 TABLE 类实例进行后续的操作了。
TABLE_SHARE 类实例中保存的也是表结构信息,TABLE 类实例中的数据就是从 TABLE_SHARE 类实例中复制过来的。
如果从二级缓存中没有读取到可以用于初始化 TABLE 类实例的表结构信息,就只能从表 frm 文件中读取了。
读取 frm 文件
到这一步,要从 frm 文件中读取表名、表注释、字段名、字段类型、字段注释、索引等所有信息,并且进行一大堆各种检查,然后创建 TABLE_SHARE 类实例,再用 TABLE_SHARE 类实例创建 TABLE 类实例。
从 frm 文件中读取信息构建 TABLE_SHARE 类实例这个过程,逻辑太复杂,执行效率就更低了。
然而不管怎样,只要表存在,并且服务器没问题,最多执行完上面 3 个步骤,就能拿到 TABLE 类实例了,然后就可以赋值给昨天说的 TABLE_LIST 的 table 属性了,从此,TABLE_LIST 就完整了。
我们在写 select 语句的过程中,经常会用到星号(*),表示查询表中所有字段,但是表中并没有一个星号字段用来表示所有字段,所以在查询准备阶段,会把星号替换为表中的所有字段。
这个替换过程比较简单,直接遍历表中的所有字段,为每个字段创建一个 Item_field 类实例,并且由于是直接遍历表中的 Field 子类实例列表,在创建 Item_field 类实例的时候就关联上了 Field 子类实例,不需要进行小蝌蚪找妈妈的过程了。
遍历完表中所有字段之后,形成一个 Item_field 列表,替换掉星号(*)对应的 Item_field 列表就行了,至此,就完成了 select 语句中星号替换为表字段的过程了。
示例 SQL 的 where 中只有一个条件(i1 > 49276),条件中的 i1 字段也是一个 Item_field 类实例,需要找到对应表中的字段,并且关联上该字段的 Field 子类实例。
where 条件中的字段找到对应 Field 子类实例的过程,是这样的:遍历 SQL 中使用到的表,在遍历每个表的过程中,根据字段名
查找表中有没有这个字段,如果没有,继续去下一个表找。如果找到了呢?那也不是就万事大吉了,像 i1 > 49276
中的 i1 字段,前面没有限定数据库名和表名,也还要继续遍历下一个表查找字段。
只有像
where 数据库名.表名.字段名 > 49276
这样,字段前面带有限定的数据库名和表名
时,找到一个字段之后,才能立马结束查找过程,而不用遍历整个查询语句中使用到的所有表。
为什么在某个表中找到了字段之后不停止查找,还要继续遍历下一个表呢?
这是为了判断字段名是不是存在冲突,如果同一个字段名可以在大于 1 个
表中找到对应的字段,说明字段名冲突了,就会报错:1052 - Column 'i1' in field list is ambiguous
。
在这个过程中,为了提升根据字段名查找对应 Field 子类实例的性能,也使用了两级缓存。
一级缓存
一级缓存在 Item_field 类实例中保存字段在表中的序号
,通过这个序号可以直接找到 Field 子类实例,就能一步到位了。
不过可惜的是,一级缓存是给 PREPARE Statement
使用的,本文中的示例 SQL 用不上。
二级缓存
二级缓存是一个 hash,key 是字段名,value 是字段 Field 子类实例。
前面说过查找字段的过程是遍历表,然后在遍历的当前表中查找字段,二级缓存中的 hash 是挂靠在表(TABLE_SHARE 类实例)上的,所以可以只用字段名作为 key。
又要可惜了,本文示例 SQL 中的 i1 字段是用不上 hash 查找了,因为只有当表中的字段数量大于等于 32
时,才会为该表创建 hash,用于字段查找。
既然字段名 hash 是挂靠在
TABLE_SHARE 类实例
上的,那么就是共享的,可以一次创建,无限次使用,边际成本为 0,为什么不是每个表都使用 hash 来进行字段查找?这点我也没想明白。
如果上面说的两级缓存都用不上,那就剩一条路了,就是:遍历
。遍历表中的每一个字段,然后比较该字段名和要查找的字段名是不是一样,如果一样那就是找到了,如果不一样,再接着遍历,直到遍历完表中的所有字段。
到这里,就把我们上一篇留下的小蝌蚪怎么找妈妈的故事
讲完了。
然而,还有一点要补充的,就是 i1 字段和常数 49276 比较时执行的比较函数
也是在填充 where 条件
这一步中确定下来的,因为 Item_field 类实例找到对应的 Field 子类实例之后,i1 字段的类型就确定了,也就知道这两个值怎么比较了。
以上,就是本文的全部内容了,今天的文章有点长,感谢大家花时间阅读,如果觉得有用,还请帮忙转发朋友圈,让更多的人看到,大家一起进步,谢谢 ^_^
预告一下,下一篇要写的内容是 MySQL 简单查询语句执行过程分析(三)从存储引擎读数据
,敬请关注!
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/6_V4kweoho1yAQRg0KYj7g
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。