前言 简介
本文经验都是我看书学习的总结的一些经验,面试常问的知识点,所以请关注后再继续观看学习!下面已经给出了书的目录!今后将按目录的顺序继续更新学习心得!接上文继续分享
目标
希望通过这些MySQL的内部原理的知识可以帮助大家培养发现新问题的洞察力,能学习和实践的结合设计出维护基于MySQL的系统。
本篇文章看起来比较枯燥,主要讲解的是MySQL的引擎,第三方引擎,性能特性龙头的引擎,看完这篇你可以知道哪种应用场景选择哪种合适的引擎,别再面试开口闭口都是InnoDB了
面试官给你出个问题:如果数据量10TB以上或者要高性能的你会选择什么引擎? 再说InnoDB就凉了 请考虑Infobright,TokuDB
目录
第一章:数据库基础知识(已更新完)
第二章:基准测试
第三章:服务器性能刨析
第四章:Schema与数据库类型优化
第五章:创建高性能的索引
第六章:查询性能优化
第七章:MySQL高级特性
第八章:优化服务器设置
第九章:操作系统和硬件优化
第十章:复制底层实现
第十一章:可扩展的MySQL
第十二章:高可用性
第十三章:云端的MySQL
第十四章:应用层优化
第十五章:备份与恢复
第十六章:MySQL用户工具
正文
MySQL的存储引擎 查询表底层结构
通过以下代码查询当前的表的底层结构信息,根据不同的业务场景需求作出相应的选择!接下来就根据下面的列名做一个描述。
Name:表名 Engine:存储引擎 Row_format:行的格式(Dynamic的行长度是可变的,一般包含可变长度的字段,如varchar或blob。Fixed的行长度是固定的,只包含固定长度的列,如char或integer。Compressed的行则只在压缩表中存在。) Rows:表中的行数(对于其他引擎来说是精确的,对于innodb来说只能是一个估值) Avg_row_length:平均每行包含的字节数 Data_length:表数据的大小以字节为单位 Max_data_length:表数据的最大容量,该值和存储引擎有关 Index_length:索引的大小 Data_free:对于MyISAM表表示已分配但目前没有使用的空间。 Auto_increment:下一个Auto_increment的值 create_time:表的创建时间 update_time:表数据的最后修改时间 check_time:使用check table或者myisamchk工具最后一次检查表的时间 collation:表的默认字符集和字符列排列规则。 checksum:如果启用,保存的是整个表的实时校验和 create_options:创建表时指定的其他选型 comment:该列包含了一些其他的额外信息 InnoDB存储引擎
InnoDB是MySQL的默认事务型引擎,也是最重要使用最广泛的。它被设计用来处理大量的短期事务,短期事务大部分情况是正常提交的,很少会被回滚。InnoDB的性能和自动崩溃恢复特性都是非常流行的。没有特定的需求下使用innodb是最好的。
InnoDB的数据存储在表空间中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。默认级别是repertable read(可重复读),并且通过间隙锁策略解决了可重复读留下的幻读的问题。间隙锁使得InnoDB不仅对查询的行进行锁定,并且也锁定了索引中的间隙。
InnoDB是基于聚族索引建立的,InnoDB的索引结构和其他存储引擎有着很大的不同。聚族索引对主键查询有着<很高的性能>
MyISAM存储引擎
MyISAM不支持事务和行级锁且崩溃后无法安全的恢复数据,尽管有那么多的缺陷,它缺可以成为最早的MySQL默认存储引擎,因为对于只读数据或者表比较小可以忍受修复的操作,则依然可以继续使用。(默认InnoDB,不建议默认MyISAM)
MyISAM会将表存储在两个文件中:数据文件和索引文件,分别以myd和myi为扩展名。MyISAM表可以包含动态或静态行。MySQL会根据表的定义来决定采用那种行格式。
特性
加锁与并发:对整张表加锁而不是针对行。读取时会对需要读到的所有表加共享锁,写入时则对表加写锁。在表有被查询的同时也可以往表里插入新的数据。 修复:对于MyISAM表,MySQL有自动修复和手工修复。这里说的是修复和事务恢复以及崩溃恢复是不同的概念。执行表休息可能会导致一些数据的丢失,而且效率非常慢。可以通过check table mytable检查表错误,repair table mytable进行修复。也可以通过myisamchk进行修复。 索引特性:支持全文索引,这是一种基于分词创建的索引,可以支持复杂的查询。 延迟更新索引键:创建MyISAM表指定了delay_key_write选项,在每次修改执行完成时,不会立刻将索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或关闭表的时候才会将对应的索引块写入磁盘。极大的提升了性能。如果主机崩溃会导致索引损坏,必须执行一遍修复才可以。 压缩表
如果创建并导入数据后不做修改,MyISAM是非常推荐使用的,压缩表可以极大得减少磁盘空间占用,最重要的是减少了磁盘的IO从而提升性能。 压缩表支持索引,但是索引只是只读的。如果导入的数据需要修改的话必须先解除压缩,再修改数据然后再次压缩。 压缩表中的记录是独立压缩的,所以读取单行的时候不需要去解压整个表。 性能
MyISAM引擎设计简单,数据以紧密格式存储,所以在某些场景下的性能很好。 有一些服务器级别的性能扩展限制。比如对索引键缓冲区的mutex,mariadb基于段的索引键缓冲区机制来避免该问题。但MyISAM最典型的性能问题还是表锁的问题,如果你发现查询长期处于locked状态,那么毫无疑问表锁就是罪魁祸首了。 Archive引擎
只支持insert和select操作。Archive引擎会缓存所有的写并利用zlib对插入的行进行压缩。所以比MyISAM表的磁盘IO更少。但是每次select查询都需要执行全表扫描。所以适合日志和采集类应用。这类做数据分析需要全表扫描或者需要更快速的insert非常好。 支持行级锁和专用的缓冲区,所以可以实现高并发的插入。在查询开始到结束前会阻止其他的select以实现一致性。 在批量插入完成前对读操作是不可见的。Archive不是一个事务型引擎而是一个针对告诉插入和压缩做了优化的简单引擎。 Blackhole引擎
blackhole没有实现任何的存储机制,他会丢弃所有插入的数据,不做任何保存,但服务器会记录blackhole表的日志,所以可以用来复制数据到备库。
Tip:这种应用方式碰到很多问题,因此不推荐,简单了解一下。拿去面试吹一吹也是很好的。
CSV引擎
csv引擎主要应用一些数据的转换,外部的csv文件可以导入到数据库操作,不支持索引。也可以把mysql表导出到外部形成excel和csv文件等。因此csv引擎可以作为一个数据转换的机制非常有用。
Federated引擎
该引擎提供了是一种很好的跨服务器的灵活性,但也经常带来问题,因此是默认是禁用的。后续版本FederatedX(了解就好)
Memory引擎
如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢失也没有关系,那么使用Memory表是非常有用的。Memory比MyISAM快一个数量级,因为所有的数据都保存在内存中,不需要进行磁盘IO。memory重启后结构会保存但是数据会丢失。
应用场景
用于查找或者映射表,例如将邮编和州名映射的表 用于缓存周期性聚合数据的结果 用于保存数据分析中产生的中间数据 Memory表支持hash索引,因此它的查询速度很快。它是表级锁,因为它的并发写入性能是非常低的。每行的长度是固定的,所以指定了varchar列实际存储时也会转换成char,这可能导致部分内存浪费。
Tip:如果MySQL在查询过程中需要临时表来保存中间结果,内部使用的临时表就是memory表,如果超出了memory的限制就会转换成MyISAM表。(memory表和临时表是两个东西。临时表是使用create temporary table语句创建的表,它可以使用任何存储引擎)
Merge引擎
merge是MyISAM的一个变种。由多少myisam合并来的虚拟表。(已被弃用)
NDB集群引擎
具体的后面章节慢慢介绍,这里只是介绍一下各种引擎问题!
组成
MySQL服务器 NDB集群存储引擎 分布式 share-nothing 容灾 高可用的NDB数据库 第三方存储引擎 OLTP类引擎
TokuDB引擎使用了一种新的分形树的索引数据结构。该结构跟内存是无关的,所以就算超出了内存性能也不会下降,也就是没用内存生命周期和碎片的问题。TokuDB是一种大数据存储引擎,拥有很高的压缩比,可以在很大的数据量上创建大量索引。特别适合在需要大量插入数据的分析型数据集的场景下使用。
面向列的存储引擎
MySQL默认是面向行的,每一行数据是一起存储的,服务器的查询也是按行为单位处理的。在大数据量梳理时,面向列的方式可能效率更高。如果不需要整行的数据,面向列的方式可以传输更少的数据。如果每一列都单独存储,那么压缩的效率也会更高。下面列举一个最有名的面向列的存储引擎infobright
infobright是最有名的面向列的存储引擎。该引擎是为数据分析和数据仓库应用设计的。数据高度压缩,按照块进行排序,每一块都对应有一组元数据。该引擎不支持索引,块结构也是一种准索引。
社区存储引擎
Aria:解决了崩溃安全恢复问题的MyISAM,也提供了MyISAM不具备的数据缓存(MyISAM只能缓存索引) Groonga:这是一款全文索引引擎,号称可以提供准确而高效的全文索引。 OQGraph:支持图操作(查找两点之间的最短路径) Q4M:该引擎在MySQL内部实现了队列操作 SphinxSE:该引擎为Sphinx全文索引搜索服务器提供了SQL接口 Spider:该引擎可以将数据切分成不同的分区,比较高效透明的实现了分片,并且可以针对分片执行并行查询(分片可以分布在不同的服务器上)。 VPForMySQL:该引擎支持垂直分区,通过一系列的代理存储引擎实现垂直分区指的是可以将表分成不同列的组合,并且单独存储。对查询来说看到的还是一张表。 如何选择合适的引擎 除非用到某些InnoDB不具备的特性,并且没有其他办法替代的可以考虑,否则都用InnoDB引擎! 如果用到全文索引:建议优先考虑InnoDB+Sphinx的组合。(而不是使用全文索引的MyISAM) 如果不在可扩展性和并发性也不在乎崩溃后的数据丢失问题,并且对InnoDB空间占用过多比较敏感,选MyISAM最合适不过了。除非万不得已,否则千万不要混合使用多种存储引擎
如果应用需要不同的存储引擎,请先考虑以下因素
事务:
首选InnoDB,如果不需要事务并且主要是select和insert那么MyISAM最好 日志型应用比较符合这一特性 备份:
如果需要在线热备份,那么选择InnoDB就是基本的要求 崩溃恢复:
数据量比较大的时候崩溃后,快速的恢复是一个需要考虑的问题。MyISAM崩溃后恢复比InnoDB发送的损坏率要高很多,而且恢复也慢,因此InnoDB是最佳选择 订单处理
如果涉及到订单那肯定涉及到事务,InnoDB是订单处理类应用的最佳选择
CD-ROM应用
如果发布一个基于CD=ROM或者DVD-ROM的并且使用MySQL数据文件的应用,可以考虑MyISAM表或者MyISAM压缩表,这样表之间可以隔离并且可以在不同介质上相互拷贝
大数据量
InnoDB可以支持数据量在3TB~5TB之间甚至更大,如果超出了10TB,可能就需要建立数据仓库了。Infobright是MySQL数据仓库最成功的解决方案。也有另外一种情况,有一些大数据库不适合infobright却可能适合TokuDB。
如何转换表的引擎 alter table将表从一个引擎修改为另一个引擎最简单的办法是使用sql语句,有一个问题就是需要很长时间MySQL会按行将数据从原表复制到一个新表。在复制期间会消耗所有的IO,同时原表会加读锁。(简单但是不太好) 可以使用mysqldump工具将数据导出至文件,然后修改create table语句的存储引擎选项,注意修改表名,因为MySQL不允许两个一样的表名。使用mysqldump默认会自动在create table前加上drop table语句,不注意的话数据没了,你估计麻烦了 综合了第一种跟第二种延展出了第三种。不需要导出整个表的数据,而是线建立一个新的存储引擎的表,然后利用insert select语法来导数据。数据量不大的话这样做是很好的。如果数据量很大的话则可以考虑做分批处理。针对每一段数据执行事务提交操作,以避免大事务产生过多的undo(可以对原表加锁确保数据的一致性) create table innodb_table like myisam_table alter table innodb_table engine=innodb insert into innodb_table select * from myisam_table MySQL版本时间线 在这里插入图片描述 总结一下
早期的MySQL是一一种破坏性创新,有诸多限制,并且很多功能只能说是二流的。在5.x版本的早期,MySQL引入了视图和存储过程等特性,期望成为“企业级”数据库,但并不算成功,MySOL5.0充满了bug,直到5.0.50以后的版本才算稳定。这种情况在MySQL5.1也依然没有太多改善。版本5.0和5.1的发布都延期了许多时日,而且Sun和Oracle的两次收购也使得社区人土有所担心。但我们认为事情还在按部就班地发展,MySQL5.5可以说是MySOL历史上质量最高的版本。Oracle收购以后帮助MySOL更好地往企业级应用的方向发展,MySQL 5.6也承诺在功能和性能方面将有显著提升。
性能测试
在解释结果之前,需要先介绍一下测试环境。测试的机器是Cisco UCS C250,两颗6核CPU,每个核支持两个线程,内存为384GB,测试的数据集是2.5GB,所以MySQL的buffer pool设置为4GB。采用SysBench的read-only只读测试进行压测,并采用InnoDB存储引擎,所有的数据都可以放人内存,因此是CPU密集型(CPU-bound) 的测试。每次测试持续60分钟,每10秒获取一次吞吐量的结果,前面900秒用于预热数据,以避免预热时的I/O影响测试结果。
现在来看看结果,有两个很明显的趋势。第一个趋势,采用了InnoDB plugin的版本,在高并发的时候性能明显更好,可以说InnoDB plugin的扩展性更好。这是可以预期的结果,旧的版本在高并发时确实存在问题。第二个趋势,新的版本在单线程的时候性能比旧版本更差。一开始可能无法理解为什么会这样,仔细想想就能明白,这是一个非常简单的只读测试。新版本的sQL语法更复杂,针对复杂查询增加了很多特性和改进,这对于简单查询可能带来了更多的开销。旧版本的代码简单,对于简单的查询反而会更有利。
原计划做一个更复杂的不同并发条件下的读写混合场景的测试(类似TPC-C),但要在不同版本间做到可比较基本是不可能的。一般来说, 新版本在复杂场景时性能有更多的优化,尤其是高并发和大数据集的情况下。
这更多地取决F业务需求而不是技术需求。理想情况下当然是版本越新越好,当然也可以选择等别第一个bug修复版本以后再采用新的大版本。如果应用还没有上限,也可以采用即将发有的新版本,以尽可能地延迟应用上线后的升级操作。
结尾 目前更新出来的是我学习到的经验知识与心得,剩下的部分将过几天持续更新!