MySQL存储引擎
说一说执行一条查询SQL查询语句的过程
- 会经过连接器、查询缓存、解析器、优化器、执行器、存储引擎这些模块
- 连接器负责建立连接、校验用户身份、接受客户端的SQL语句
- 在查询缓存中,如果命中缓存,直接返回
- 分析器对SQL语句进行语法分析、词法分析
- 优化器会基于查询成本的考虑,对每个索引进行成本分析,从中选择查询成本最小的执行计划。同时缓存记录给查询缓存
- 执行器会根据执行计划来执行查询语句,从存储引擎中读取记录,返回给客户端
MySQL存储引擎有哪些
有InnoDB、MyISAM、Memory
InnoDB是MySQL默认的存储引擎,支持事务、行级锁,具有事务提交、回滚和崩溃恢复功能
MyISAM和InnoDB有什么区别
从数据存储、B+树结构、锁粒度、事务这四个角度来分析
- 数据存储:InnoDB存储数据采取的是索引组织表,在索引组织表中,索引即数据,数据即索引,因此表数据和索引数据在同一个文件中。MyISAN存储数据采用的是堆表,数据和索引分开存储,因此表数据和索引数据分别放在不同的两个文件中
- 索引组织表有两个优势:1. 在索引组织表中,索引和数据在同一个B+树,相比非聚簇索引每次查询都需要回表,因此聚簇索引中获取数据比非聚簇索引快。2. 在索引组织表中,如果记录的非索引记录发生了变化,则其他索引无须进行维护。而当堆表中的位置发生了变化,那么所有的索引地址都需要更新
- B+树结构:InnoDB引擎B+树叶子节点存储索引+数据,MyISAM引擎叶子节点存储索引+数据地址
- 锁粒度:InnoDB引擎支持行级锁,MyISAM不支持行级锁,支持表锁。因为MyISAM引擎不支持聚簇索引,所以无法实现行锁,出现多条线程同时读写数据时,只能锁住整张表。而InnoDB由于支持聚簇索引,每个索引最终都会指向聚簇索引中的索引键,因此出现并发事务时,InnoDB只需要锁住聚簇索引的数据即可,而不需要锁住整张表,因此并发性能更高
- 事务:InnoDB支持事务,MyISAM不支持事务。使用InnoDB存储引擎的表,可以借助undo-log日志实现事务机制,支持多条SQL组成一个事务,可以保证发生异常的情况下,组成这个事务的SQL到底回滚还是提交。而MyISAM并未设计类似的技术,在启动时不会在内存中构建undo_log_buffer缓冲区,磁盘中也没有相应的日志文件,因此MyISAM并不支持事务机制
MySQL为什么选择InnoDB作为默认引擎
最主要原因是InnoDB支持事务,其他引擎不支持
- 事务支持:InnoDB支持事务,保证了ACID(原子性、一致性、隔离性、持久性),MyISAM是不支持事务的
- 并发性能:InnoDB因为支持聚簇索引,可以使用行级锁,在并发条件下只需要对行数据加锁,不需要对整张表加锁。而MyISAM只能对整张表加锁,并发效率低
- 崩溃恢复:InnoDB通过redolog日志实现了崩溃恢复,保证了数据了持久性和一致性。MyISAM不支持崩溃恢复
用count(*)哪个存储引擎会更快
在MyISAM中,每张数据表都有一个meta信息维护了row_count的值,由表级锁一致性,直接读取row_count的值就是count函数的执行结构。
因此如果查询语句中没有where查询条件,MyISAM更快。如果有where查询条件性能都差不多,都需要一行一行遍历地统计
NULL值是如何存储的?
MySQL行格式会用NULL值列表来标记值为NULL的列,每个列对应一个二进制位,如果列的值为NULL,就会标记二进制位为1,否则是0。所以NULL值并不会存储在数据格式中的真实数据部分
char和varchar有什么区别?哪个性能更好
区别:
- char是固定长度的字符串类型,它是数据库中占用固定的存储空间,无论存储的大小是多少,都会占用定义时的固定长度。如果存储的字符串长度小于定义的字符串长度,则会用空格填充。比如定义一个char(10)的字符串,但是只用了5字节,会自动填充5字节
- varchar是变长长度的字符串类型,实际存储时占用实际字符串长度的大小。但是还需要额外1-2字节存储可变长字符串长度的空间
性能:
- 站在CPU角度来看,理论上CHAR比VARCHAR快,因为VACHAR有一个长度标识参与运算
- 但是在实际中,Innodb buffer pool 小于表大小时,磁盘读写成为了性能的关键因素。而VARCHAR更短,性能反而比CHAR高。但是当Innodb buffer pool足够大时,CHAR和VARCHAR性能差异不大
一个字段是VARCHAR(10),但它实际上只有6个字节,那他在内存空间的大小是多少?在文件中的存储空间大小是多少?
varchar是可变长字符串长度,保存到文件中,只会存储实际使用的字符串大小。但是内存是按varchar最大值来固定分配大小。
因此在内存中会占用10字节。在文件中占用6字节,并且都会用1-2字节存储可变长字符串长度的空间
varchar可变长字符串长度的空间大小是1字节还是2字节取决什么?
如果硬件内存特别大,MySQL缓存是否可以替代Redis
不能
- bufferpool结构,日志技术,事务并发,存储模型等等模块,都是面向磁盘页而设计的,因此其首要目标不是减少内存代价,而是I/O代价。
- 其次,Mysql查询走的是B+树索引,时间复杂度是O(logN),Redis有Hash数据对象的时候,查询复杂度是O(1)
- 最后,MySQL在更新数据的时候,为了保证事务的隔离性,需要加锁,而Redis更新操作不需要加锁。还有MySQL为了保证数据的持久性,还需要刷盘redolog和binlog日志,Redis可以选择不持久化。因此即使buffer pool无限大,MySQL缓存的性能还是没有Redis好
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 cloud_fly blog!