Mysq之索引(二)——存储引擎和聚集索引、非聚集索引

1、 什么是存储引擎
存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。
在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql数据库提供了多种存储引擎。如下图:
在这里插入图片描述
工作一般主要使用两种:InnoDB和MyISAM。
InnoDB 事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。MySQL 5.5.5 之后,InnoDB 作为默认存储引擎。
MyISAM 是基于 ISAM 的存储引擎,并对其进行扩展,是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务。


2、不同引擎存储的文件
表在创建的时候旋转innodb引擎,会在数据库文件夹生成2个文件,一个是.frm,一个是.ibd。如下图,但是我的.ibd文件没有展示,可能是版本问题或者哪里的配置要修改一下,大家先看。
表在创建的时候旋转MyISAM 引擎,会在数据库文件夹生成3个文件,.frm、.MYD、和MYI。
在这里插入图片描述
1、 .frm文件:保存了每个表的元数据,包括表结构的定义等。类似:

CREATE TABLE `test_innodb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

2、.MYD文件:存储表中所有的数据行文件(磁盘文件指针:类似表行数据的地址)
3、.MYI文件:存放表的索引(就是表中PRIMARY KEY (id))
4、.ibd:存放表中数据文件(相比myisam索引和data合并在一个文件中)

例子1 myisam存储结构:
假如我们从myisam存储引擎根据索引col1查询49的数据,先从myi文件中查找49的索引,然后从myisam中拿到叶子节点的data,根据data中的磁盘文件指针去myd文件中拿到表中行数据。
myisam存储结构
例子2 innodb存储结构:
innodb存储结构


3、面试题目1:为什么innodb一定要有主键,并且推荐使用整形的自增主键而不是UUID?
没有给innodb的表建立主键表页建立,mysql底层会给你的表具有唯一标识这列数据的字段作为主键索引,如果没有找到会自动给你生成一个隐藏列。B+树存储主键索引,必须要有主键,主键索引用来维护表中的数据。
为什么推荐使用整形的自增主键?
1、UUID占据更多的空间
2、如果UUID作为主键的话,B+树在插入数据的时候要去根据主键去比较大小插入,UUID比较要转换ACII去比较,字符串会消耗大量的时间效率。
3、使用自增主键时,叶子节点从左到右自增的,新插入的数据直接放在后面就好,分裂发生的概率非常小。而用UUID不是自增的,每次比较的时候,如果索引节点中存储满了之后只能裂变,大量分裂以及树的平衡效率非常低。
什么是裂变:
树的分裂过程


4、MyISAM与InnoDB 的区别
.1、 InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
**2、InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
3. InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
5. 那么为什么InnoDB没有了这个变量呢?
因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。
如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据。和上面提到的问题一样,如果此时存在多个事务的话这种方案也不太好用。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS
6. InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁

例如:
    t_user(uid, uname, age, sex) innodb;
    uid PK
    无其他索引
    update t_user set age=10 where uid=1;             命中索引,行锁。
    update t_user set age=10 where uid != 1;           未命中索引,表锁。
    update t_user set age=10 where name='chackca';    无索引,表锁。

7、InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有
8、Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
Innodb:frm是表定义文件,ibd是数据文件
Myisam:frm是表定义文件,myd是数据文件,myi是索引文件

如何选择:
1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。
3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;
4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。


5、聚集索引和非聚集索引
聚集索引:innodb主键索引就可以当作是聚集索引。
把索引元素和data聚集在一起,或者说页节点包含了完整的数据记录
非聚集索引:myisam主键索引就可以当作是聚集索引非聚集索引:
索引元素和data没有聚集在一起,索引和数据分开

聚集索引和非聚集索引是不是秒懂。

再来看看上篇的几个面试问题:
1. 为什么要给表加上主键?
2. 为什么加索引后会使查询变快?
3. 为什么加索引后会使写入、修改、删除变慢?
4. 什么情况下要同时在两个字段上建索引?

相信1-3你已经有了答案。问题4会在下章在详细阐述。索引的使用

发布了68 篇原创文章 · 获赞 9 · 访问量 7441

猜你喜欢

转载自blog.csdn.net/u013025649/article/details/103872380