MySQL(二) 存储引擎
执行一条查询SQL语句的全过程
MySQL执行一条查询SQL语句的时候,会经过连接器、查询缓存、解析器、预处理器、优化器、执行器、存储引擎这些模块。
- 第一步,MySQL的连接器会负责建立连接、校验用户身份、接收客户端的SQL语句;
- 第二步MySQL会在查询缓存中查找数据,如果命中直接返回数据给客户端,否则就需要继续往下查询,不过查询缓存功能在MySQL8.0版本被删除了,原因是只要对这张表进行了写操作,这张表的查询缓存就会失效,所以在实际场景中,查询缓存的命中率其实不高;
- 第三步MySQL的解析器会对SQL语句进行词法分析和语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
- 第四步MySQL的预处理器检查表或字段是否存在,将
select *
中的*
符号扩展为表上的所有列; - 第五步MySQL的优化器会基于查询成本的考虑,会判单每个索引的执行成本,从中选择查询成本最小的执行计划;
- 第六步MySQL的执行器会根据执行计划来执行查询语句,从存储引擎读取记录,返回给客户端。
MySQL ⽀持哪些存储引擎
MySQL常见的存储引擎有InnoDB、MyISAM、Memory.
InnoDB引擎,是MySQL默认的存储引擎,支持事务和行级锁,具有事务提交、回滚和崩溃恢复功能(redo log)。(索引组织表,索引和数据一起储存,聚簇索引叶子结点放数据)
- MyISAM,是不支持事务和行级锁和崩溃恢复的,而且由于只支持表锁,锁的粒度比较大,更新性能比较差,我认为它比较适合读多写少的场景。(堆表,索引和数据分开储存,叶子结点放数据物理地址)
- Memory了解不多,大概是将数据存储在内存中,所以数据的读写还是比较快的,但是数据不具备持久性,我觉得适用于临时存储数据的场景。
用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字节的空间。
如果硬件内存特别大,MySQL缓存能否替代Redis
不能替代。
MySQL所有模块,比如buffer pool、日志技术、事务并发模块,都是面向磁盘页而设计的,因此其首要目标不是减少内存访问的代价,而是I/O代价,所以内存访问代价却并不是最优的选择,而Redis是面向内存而设计的数据库。
MySQL在内存查询一个数据页的时候,都需要先查页表,也就是需要走b+树的搜索过程,时间复杂度是O(logdN),而Redis提供了很多种的数据类型,比如用Hash数据对象的时候,可以在O(1)时间复杂度查到数据。
MySQL在更新数据的时候,MySQL为了保证事务的隔离性,是需要加锁的,而Redis更新操作都是不需要加锁的,还有MySQL为了保证事务的持久性,还需要刷盘redolog日志和binlog日志,Redis可以选择不持久化数据。因此,即使buffer pool无限大,MySQL缓存的性能还是没有Redis好的。