InnoDB是MySQL默认的事务型存储引擎,只有在需要InnoDB不支持的特性时,才考虑使用其它存储引擎。
采用MVCC来支持高并发,并且实现了四个标准的隔离级别,默认级别是可重复读。
表是基于聚簇索引建立的,它对主键的查询性能有很高的提升。
内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够自动在内存中创建哈希索引以加速读操作的自适应哈希索引、能够加速插入操作的插入缓冲区等。
通过一些机制和工具支持真正的热备份。
存储引擎MyISAMMyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但MyISAM不支持事务和行级锁,而且崩溃后无法安全恢复。
只能对整张表加锁,而不是针对行。
可以手工或者自动执行检查和修复操作,但是和事务恢复以及崩溃恢复不同,可能导致一些数据丢失,而且修复操作是非常慢的。
可以包含动态或者静态的行。
如果指定了DELAY_KEY_WRITE选项,在每次修改执行完成时,不会立即将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘。这种方式可以极大的提升写入性能,但是在数据库或者主机崩溃时会造成索引损坏,需要执行修复操作。
如果表在创建并导入数据以后,不会再进行修改操作,那么这样的表适合采用MyISAM压缩表。
对于只读数据,或者表比较小、可以容忍修复操作,则依然可以继续使用MyISAM。
MyISAM设计简单,数据以紧密格式存储,所以在某些场景下性能很好。
比较事务:InnoDB是事务型的。
备份:InnoDB支持在线热备份。
崩溃恢复:MyISAM崩溃后发生损坏的概率比InnoDB高很多,而且恢复的速度也更慢。
并发:MyISAM只支持表级锁,而InnoDB还支持行级锁。
其它特性:MyISAM支持全文索引,地理空间索引。
二、数据类型1.整型TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT分别使用8,16,24,32,64位存储空间,一般情况下越小的列越好。
INT(11)中的数字只是规定了交互工具显示字符的个数,对于存储和计算来说是没有意义的。
2.浮点数FLOAT和DOUBLE为浮点类型,DECIMAL为高精度小数类型。CPU原生支持浮点运算,但是不支持DECIMAl类型的计算,因此DECIMAL的计算比浮点类型需要更高的代价。
FLOAT、DOUBLE和DECIMAL都可以指定列宽,例如DECIMAL(18,9)表示总共18位,取9位存储小数部分,剩下9位存储整数部分。
3.字符串主要有CHAR和VARCHAR两种类型,一种是定长的,一种是变长的。
VARCHAR这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行UPDATE时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM会将行拆成不同的片段存储,而InnoDB则需要分裂页来使行放进页内。
VARCHAR会保留字符串末尾的空格,而CHAR会删除。
4.时间和日期MySQL提供了两种相似的日期时间类型:DATATIME和TIMESTAMP。
5.DATATIME能够保存从年到年的日期和时间,精度为秒,使用8字节的存储空间。
它与时区无关。
默认情况下,MySQL以一种可排序的、无歧义的格式显示DATATIME值,例如“-01-:37:08”,这是ANSI标准定义的日期和时间表示方法。
6.TIMESTAMP和UNIX时间戳相同,保存从年1月1日午夜(格林威治时间)以来的秒数,使用4个字节,只能表示从年到年。
它和时区有关。
MySQL提供了FROM_UNIXTIME()函数把UNIX时间戳转换为日期,并提供了UNIX_TIMESTAMP()函数把日期转换为UNIX时间戳。
默认情况下,如果插入时没有指定TIMESTAMP列的值,会将这个值设置为当前时间。
应该尽量使用TIMESTAMP,因为它比DATETIME空间效率更高。
索引索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
索引能够轻易将查询性能提升几个数量级。
对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和使用索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。
1.B+Tree索引《高性能MySQL》一书使用B-Tree进行描述,其实从技术上来说这种索引是B+Tree。
B+Tree索引是大多数MySQL存储引擎的默认索引类型。
因为不再需要进行全表扫描,只需要对树进行搜索即可,因此查找速度快很多。
可以指定多个列作为索引列,多个索引列共同组成键。B+Tree索引适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。
除了用于查找,还可以用于排序和分组。
如果不是按照索引列的顺序进行查找,则无法使用索引。
2.哈希索引基于哈希表实现,优点是查找非常快。
在MySQL中只有Memory引擎显式支持哈希索引。
InnoDB引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在B+Tree索引之上再创建一个哈希索引,这样就让B+Tree索引具有哈希索引的一些优点,比如快速的哈希查找。
限制:哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能影响并不明显;无法用于分组与排序;只支持精确查找,无法用于部分查找和范围查找;如果哈希冲突很多,查找速度会变得很慢。
3.空间索引(R-Tree)MyISAM存储引擎支持空间索引,可以用于地理数据存储。
空间索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。
4.全文索引MyISAM存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较索引中的值。
使用MATCHAGAINST,而不是普通的WHERE。
索引的优点大大减少了服务器需要扫描的数据量;
帮助服务器避免进行排序和创建临时表;
将随机I/O变为顺序I/O。
索引优化1.独立的列
在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法使用索引。
例如下面的查询不能使用actor_id列的索引:
SELECTactor_idFROMsakila.actorWHEREactor_id+1=5;
2.前缀索引
对于BLOB、TEXT和VARCHAR类型的列,必须使用前缀索引,只索引开始的部分字符。
对于前缀长度的选取需要根据索引选择性来确定:不重复的索引值和记录总数的比值。选择性越高,查询效率也越高。最大值为1,此时每个记录都有唯一的索引与其对应。
多列索引
在需要使用多个列作为条件进行查询时,使用多列索引比使用多个单列索引性能更好。例如下面的语句中,最好把actor_id和film_id设置为多列索引。
SELECTfilm_id,actor_idFROMsakila.film_actorWhEREactor_id=1ANDfilm_id=1;
4.索引列的顺序
让选择性最强的索引列放在前面,例如下面显示的结果中customer_id的选择性比staff_id更高,因此最好把customer_id列放在多列索引的前面。
聚簇索引聚簇索引并不是一种索引类型,而是一种数据存储方式。
术语“聚簇”表示数据行和相邻的键值紧密地存储在一起,InnoDB的聚簇索引的数据行存放在B-Tree的叶子页中。
因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
优点
可以把相关数据保存在一起,减少I/O操作;
因为数据保存在B-Tree中,因此数据访问更快。
缺点
聚簇索引最大限度提高了I/O密集型应用的性能,但是如果数据全部放在内存,就没必要用聚簇索引。
插入速度严重依赖于插入顺序,按主键的顺序插入是最快的。
更新操作代价很高,因为每个被更新的行都会移动到新的位置。
当插入到某个已满的页中,存储引擎会将该页分裂成两个页面来容纳该行,页分裂会导致表占用更多的磁盘空间。
如果行比较稀疏,或者由于页分裂导致数据存储不连续时,聚簇索引可能导致全表扫描速度变慢。
覆盖索引索引包含所有需要查询的字段的值。
优点
因为索引条目通常远小于数据行的大小,所以若只读取索引,能大大减少数据访问量。
一些存储引擎(例如MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。
对于InnoDB引擎,若二级索引能够覆盖查询,则无需访问聚簇索引。
B-Tree和B+Tree原理
B-Tree
为了描述B-Tree,首先定义一条数据记录为一个二元组[key,data],key为记录的键,data为数据记录除key外的数据。
B-Tree是满足下列条件的数据结构:
所有叶节点具有相同的深度,也就是说B-Tree是平衡的;
一个节点中的key从左到右非递减排列;
如果某个指针的左右相邻key分别是keyi和keyi+1,且不为null,则该指针指向节点的所有key大于keyi且小于keyi+1。
在B-Tree中按key检索数据的算法非常直观:首先从根节点进行二分查找,如果找到则返回对应节点的data,否则对相应区间的指针指向的节点递归进行查找,直到找到节点或找到null指针,前者查找成功,后者查找失败。
由于插入删除新的数据记录会破坏B-Tree的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持B-Tree性质。
B+Tree
与B-Tree相比,B+Tree有以下不同点:
每个节点的指针上限为2d而不是2d+1;
内节点不存储data,只存储key,叶子节点不存储指针。
文章长度受限,本文先介绍到这里