说一说执行一条SQL语句的执行过程
执行一条语句会经过连接器、查询缓存、解析器、优化器、执行器、存储引擎。
第一步,连接器负责建立连接、校验用户身份、接受客户端的SQL语句。
第二步,MySQL会在查询缓存中查找数据,如果命中直接返回数据给客户端,否则需要继续向下查询,不过查询缓存功能在MySQL 8.0版本被删除了 ,原因是只要对这张表进行写操作,这张表的查询缓存就会失效,所以在实际场景中,查询缓存的命中率其实不高。
第三步:MySQL的解析器会对SQL语句进行词法分析和语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型。
第四步:MySQL的优化器会基于查询成本的考虑,会判断每个索引的执行成本,从中选择查询成本最小的执行计划。
第五步:MySQL的执行器会根据执行计划来执行查询语句,从存储引擎读取记录,返回给客户端。
MySQL 存储引擎有哪些?
MySQL常见的存储引擎有InnoDB、MyISAM、Memory
- 对于InnoDB比较熟悉,它是MySQL默认的存储引擎,支持事务和行级锁,具有事务提交、回滚和崩溃恢复功能。
- MyISAM引擎是不支持事务和行级锁的,而且由于只支持表锁,锁的粒度比较大,更新性能比较差,我认为它比较适合读多写少的场景。
- Memory引擎是将数据存储在内存中,所以数据的读写比较快,但是数据不具备持久性,我觉得适用于临时存储数据的场景。
MyISAM和InnoDB存储引擎有什么区别?
InnoDB 引擎和 MyISAM引擎在数据存储上有很大区别,InnoDB 引擎是将表数据和索引数据存放在同一个文件的,而MyISAM 引擎是将表数据和索引数据分开存储的。所以,InnoDB 引擎 B+ 树索引中的叶子结点存储的是索引和数据,MyISAM 引擎 B+ 树索引中的叶子结点存储的是索引和数据地址。
用count(*) 那个存储引擎会更快?
如果查询语句没有where 查询条件的话,用MyISAM 引擎会比较快,因为MyISAM 引擎的每张表会用一个变量存储表的总记录个数,执行count函数的时候,直接读取这个变量就行了。而InnoDB 引擎执行count函数的时候,需要通过遍历的方式来统计记录个数。
如果查询语句中有where查询条件的话,MyISAM和InnoDB引擎执行count的时候,性能都差不多,都需要根据查询条件一行行的进行统计。
null 值是如何存储的?
MySQL行格式中会用 null值列表 来标记为Null的列,每个列对应一个二进制位,如果列的值为null,就会标记二进制位为1,否则为0,所以null值并不会存储在行格式中的真实数据部分。
null值列表最少会占用1字节空间,当表中所有列都定义为NOT NULL, 行格式中就不会有NULL值列表,这样就可以至少节约1字节的空间。
char 和 varchar 有什么区别?
char 是固定长度的字符串类型,它在数据库中占用固定的存储空间,无论实际存储的数据长度是多少,都会占用定义时指定的固定长度,如果实际存储的字符串长度小于定义的长度,系统会自动用空格填充。
varchar 是可变长度的字符串类型。实际存储时只占用实际字符串长度的空间,不会进行空格填充。
假如说一个字段是varchar(10),但它其实只有6个字节,那它在内存中占的存储空间是多少?在文件中占的存储空间是多少?
内存会占用10字节,文件存储空间会占用6字节,并且还会额外用1-2字节存储[可变长字符串长度]的空间。
如果硬件内存特别大,MySQL缓存能否代替redis?
我觉得还是不能代替的。
MySQL所有模块,比如buffer pool、日志技术、事务并发模块,都是面向磁盘页而设计的,因此其首要目标不是减少内存访问的代价,而是I/O代价,所以内存访问代价却并不是最优的选择,而Redis是面向内存而设计的数据库。
MySQL在内存查询一个数据页的时候,都需要先查页表,也就是需要走b+树的搜索过程,时间复杂度是O(logN),而Redis提供了很多种的数据类型,比如用Hash数据对象的时候,可以再O(1)时间复杂度查到数据。
MySQL在更新数据的时候,MySQL为了保证事务的隔离性,是需要加锁的,而Redis更新操作都是不需要加锁的,还有MySQL为了保证事务的持久性,还需要刷盘redolog日志和binlog日志,Redis可以选择不持久化数据。
因此,即便 buffer pool 无限大,MySQL 缓存的性能还是没有Redis好。
本文详细描述了SQL语句在MySQL中的执行步骤,包括连接器、查询缓存、解析器、优化器和执行器的作用。重点介绍了InnoDB、MyISAM和Memory等存储引擎的特点以及它们在不同场景下的应用。

被折叠的 条评论
为什么被折叠?



