我们经常说到的存储引擎是说数据库级别还是说表级别?
答:表级别。(数据库级别也可以设置,但是最终它的级别生效是在表级别)
1、MylSAM存储引擎索引实现
MylSAM索引文件和数据文件是分离的(非聚集)。先从索引文件中找到数据的磁盘位置,再到数据文件中找到索引对应的数据内容。
MyIsam 存储引擎独立于操作系统,简单说就是可以在windows上使用,也可以将数据转移到Linux操作系统上。系统兼容性很好!!!。这种存储引擎在建表的时候,它会创建3个文件。分别是(.frm, .MYD, .MYI),简单说明一下:.frm 存储表的定义(也就是表结构啦),.MYD (巧记:data数据)就是表里面的数据,.MYI(巧记index索引、目录)存储索引。这样的划分操作系统对大文件的操作是比较慢的,这样将表分为三个文件,那么.MYD这个文件单独来存放数据自然可以优化数据库的查询等操作。
特点:
- 不支持事务
- 不支持外键
- 查询速度很快。如果数据库insert和update的操作比较多的话采用表锁效率低(建议使用innodb)。
2、InnoDB存储引擎索引实现
lnnoDB索引实现(聚集)
- 表数据文件本身就是按B+Tree组织的一个索引结构文件
- 聚集索引-叶节点包含了完整的数据记录
- 为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?
- 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
InnoDB支持事务和行锁设计、支持外键、支持全文索引(InnoDB1.2之后版本),主要面向OLTP(On-Line Analytical Processing,在线事务处理)数据库应用,支持类似Oracle的非锁定读,即默认读取操作不会产生锁。
知识拓展:
MyISAM不支持事务和外键主要是因为其设计目标是提高读取操作性能,而不是优化写入操作。事务是一组操作的集合,要求它们全部成功或全部失败。MyISAM不支持事务,因为它为了减少I/O操作,使用了表级锁定(Table-Level Locking),这会导致当多个事务同时访问同一个表时出现性能瓶颈。而InnoDB则采用了行级锁定(Row-Level Locking)来支持事务,它能够限制一次事务只锁定需要修改的行,提高并发性。 外键用于建立表之间的关联性约束。
MyISAM不支持外键,因为它是一种低级别的数据存储引擎,不支持对跨表操作的完整性检查和维护。InnoDB则支持外键,因为它支持事务,并且使用了行级锁定来维护数据完整性。
InnoDB通过使用多版本并发控制MVCC来获的高并发性,并且实现SQL标准的四种隔离级别,默认是REPEATABLE, 同时使用next-key locking的策略来避免幻读
除此之外,InnoDB存储引擎还提供了以下四种高性能和高可用的功能: (1)插入缓冲(insert buffer) (2)二次写(double write) (3)自适应哈希索引(adaptive hash index) (4)预读(read ahead)
对于表中数据的存储,InnoDB存储引擎采用聚集clustered的方式,因此每个表的数据都是按照主键的顺序进行存放,如果没有显示的指定主键,InnoDB默认会为每一行生产一个6字节的ROWID并以此作为主键;每个InnoDB存储引擎的在磁盘上存储(InnoDB,数据存储在磁盘上)为两个文件: .frm文件(表结构的数据文件) .ibd文件(用来存储数据和索引文件)
对于InnoDB表,自动增长列必须是索引。如果是组合索引,也必须是组合索引的第一列,但是对于MyISAM 表,自动增长列可以是组合索引的其他列,这样插入记录后,自动增长列是按照组合索引的前面几列进行排序后递增的。
3、MyISAM和InnoDB的区别
- 数据存储的方式不同,MyISAM中的数据和索引是分开存储的,而InnoDB是把索引和数据存储在同一个文件里面。
- 对于事务的支持不同,MyISAM不支持事务,而InnoDB支持ACID特性的事务处理
- 对于锁的支持不同,MyISAM只支持表锁,而InnoDB可以根据不同的情况,支持行锁,表锁,间隙锁,临键锁
- MyISAM不支持外键,InnoDB支持外键
我们在实际应用中,可以根据不同的场景来选择合适的存储引擎:
- 如果需要支持事务,那必须要选择InnoDB。
- 如果大部分的表操作都是查询,可以选择MyISAM。
4、为什么建议InnoDB表必须建主键
首先,我们知道InnoDB采用B+树作为存储结构,那么必然需要一个列作为key,什么是key?
一个B+树的节点可以存储key、地址、行数据(仅叶子节点),key 就是不重复的值且可以比较(确保树进行分裂时,可以确定是左孩子还是右孩子)。
我们知道主键的特点就是主键的值不可重复,也不可为空,正好符合B+树key的要求
聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引(确切说会选择一个唯一非空的列作为主键)代替。如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。
InnoDB 只聚集在同一个页面中的记录。包含相邻健值的页面可能相距甚远。
如果你已经设置了主键为聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可
聚簇索引性能最好而且具有唯一性,所以非常珍贵,必须慎重设置。一般要根据这个表最常用的SQL查询方式来进行选择,某个字段作为聚簇索引,或组合聚簇索引,这个要看实际情况
5、为什么主键通常建议使用自增id
聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。聚簇索引的顺序和磁盘中数据的存储顺序是一致的,如果主键不是自增id,那么可以想 象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。
补充:因为MyISAM的主索引并非聚簇索引,那么他的数据的物理地址必然是凌乱的,拿到这些物理地址,按照合适的算法进行I/O读取,于是开始不停的寻道不停的旋转。聚簇索引则只需一次I/O。(强烈的对比)
不过,如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。
为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?(另一个参考答案)
- 为什么要设置主键 ?
毫无疑问的是,当对Mysql中的表设置了InnoDB存储引擎的时候,那么就需要对一列数据建立索引,方便快速查找,如果不设置主键的,Mysql会在表中逐列对比寻找无重复项的列作为逐渐,如果没有查找到,那么Mysql会在表中添加默认列作为主键。如果不设置主键列,那么Mysql会消耗大量的资源去寻找索引列或者是创建新的索引列,如果设置了索引列那么将极大的降低Mysql的资源消耗。
- 为什么要采用整型的数据 ?
Mysql底层对数据查找的时候,会涉及到大量的对比操作,如果采用UUID的字符串模式,那么Mysql在对比过程中会消耗资源用于字符串中每个字符的对比,这样做将极大的消耗系统的性能。
- 为什么要采用自增主键 ?
了解 B+ 树的节点存储机制的话,就一定会知道当某个节点的索引数量达到阈值的时候会分裂节点重新调整树的平衡。这样做对系统性能的消耗是相当不友好,在 B+ 树的叶子节点中,通过双向指针维护了一根将索引按照升序排列的双向链表,采用自增主键,新的索引将会被添加在链表的尾部,避免了B+ 树的分裂所带来的系统消耗。
6、InnoDB的索引怎么实现的?
重点:数据结构(B+树)、聚簇索引等
InnoDB的索引实现基于B+树索引结构,但与MyISAM不同的是,InnoDB的B+树索引采用了聚簇索引的设计方法。聚簇索引意味着B+树的叶子节点存储的是数据记录本身,而不是指向数据记录的指针。这使得数据的查询速度更快,因为数据记录存储在索引树的同一层级,而不是与指针存储在不同的磁盘区域。
对于每个表,InnoDB都会自动为其建立一个名为“聚簇索引”的索引,该索引的键值是表的主键或唯一索引。当需要查询或操作表时,InnoDB使用聚簇索引来快速定位数据行,这使得聚簇索引对于查询基于主键或唯一索引的单个数据行十分有效。
此外,InnoDB还支持创建多列索引、全文索引、空间索引等各种类型的索引,从而满足不同场景的需求。 为了进一步优化查询性能,InnoDB还采用了一些高级技术,比如“自适应哈希索引”技术,用于在索引与数据记录之间建立一个哈希表,以加速基于某些查找条件的查询。同时,它还支持事务和行级锁定,使得多个用户可以同时对同一表进行修改和查询,避免了竞争和死锁问题。
总之,InnoDB的索引实现结合了聚簇索引、多种类型索引、自适应哈希索引等特性,使其具有高性能、高可靠性和扩展性,为复杂的应用程序开发和优化提供了广泛的支持。
7、InnoDB、MyISAM 和 Memory 分别支持的索引类型
| 索引类型 | InnoDB引擎 | MyISAM引擎 | Memory引擎 |
|---|---|---|---|
| B+Tree索引 | Yes | Yes | Yes |
| Hash索引 | No(不支持hash索引,但是在内存结构中有一个自适应hash索引) | No | Yes |
| Full-Text索引 | Yes(MySQL5.6版本后支持) | Yes | No |
B+Tree 存储千万级的数据只需要 3-4 层高度就可以满足,这意味着从千万级的表查询目标数据最多需要 3-4 次磁盘 I/O,所以B+Tree 相比于B树和二叉树来说,最大的优势在于查询效率很高,因为即使在数据量很大的情况,查询一个数据的磁盘 I/O 依然维持在3-4次。