网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
B+Tree索引
MyISAM和InnoDB实现B+Tree索引方式的区别
MyISAM
B+Tree叶子节点data域存放的 是数据记录的地址。在检索索引的时候,首先按照B+Tree搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录,这种称为非聚簇索引。
InnoDB
其数据文件本身就是索引文件,对于MyISAM(索引文件和数据文件是分离的),InnoDB的数据文件本身就是按照B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这种称为聚簇索引(聚集索引)。
其余的索引都只是作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址。在根据主索引搜索的时候,直接找到key所在的节点即可取出数据,在根据辅助索引查找的时候,则需要先取出主键的值,再走一遍主索引。因此在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。
覆盖索引
什么是覆盖索引
如果一个索引包含了所有查询的字段的值,我们就称之为覆盖索引。在InnoDB存储引擎中,如果不是主键索引,叶子节点存储的是主键+列值,最终我们在查询的时候还是需要回表查询的,也就是说需要通过主键再查找一次,这样做会比较慢,而覆盖索引就是查出来的列和索引是一一对应的,不需要回表操作。
覆盖索引举例
我们为username、age创建了索引,我们如果执行下面的SQL语句:
select username , age from user where username = 'xiaolin' and age = 18
在查询数据库的时候,要查询的列在叶子节点都有,所以不需要回表查询。
选择索引和利用索引的原则
- 单行访问时很慢的。如果服务器从存储中读取一个数据库只是为了获取其中的一行,那么就浪费了很多的工作,最好读取的块中能包含尽可能多所需要的行。
- 按顺序访问范围数据是很快的。原因有两个:①顺序IO不需要多次磁盘寻道,所以比随机IO要快很多,尤其是对于机械硬盘来说。②如果服务端能够按顺序读取数据,那么就不再需要额外的排序操作,并且Group by查询也无需再做排序。
- 索引覆盖查询时很快的,如果一个索引包含了查询所需的所有列,那么存储引擎就不再需要回表查找,避免了大量的单行访问。
最左前缀原则
MySQL中的索引可以以一定的顺序引用多列,这种索引叫做联合索引,比如user表的name和age合起来作为一个索引就是联合索引,而最左前缀的原则时指,如果查询的时候查询条件精确匹配索引的左边连续一列或者几列,则此索引就可以命中。
# 可以命中索引
select * from user where name = xx and age = xx ;
# 可以命中索引
select * from user where name = xx ;
# 无法命中索引
select * from user where city = xx ;
有一个需要注意的点,查询的时候如果两个条件都用上了,但是顺序不同,比如:
select * from user where city = xx and name = xx ;
这个时候查询引擎会自动优化为匹配联合索引的顺序,索引还是可以命中的,但是不推荐这样去做,为了保险起见,还是按照索引的顺序去书写。
由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重后的个数,较多的放前面,Order by字句也遵循这个规则。
避免冗余索引
冗余索引指的是索引的功能相同,能命中第一个肯定就能够命中第二个索引,比如(name,age)和name这两个索引就是冗余索引,能够命中前者的查询就必定能够命中后者,在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
MySQL 5.7 版本后,可以通过查询 sys
库的schema_redundant_indexes
表来查看冗余索引。
索引的缺点
- 创建索引和维护索引需要耗费许多时间,当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低SQL的执行效率。
- 占用物理空间:索引需要使用物理文件存储,也会消耗一定的物理空间。
B树和B+树的区别
- B树的每个节点都是存储了Key和Data,Key是一条数据记录的键值,是唯一的。Data存储的是除Key以外的数据。而B+树只在叶子节点存储Data数据,这样非叶子节点就能够存储更多的Key,所以B+树相对来说更加的矮胖,因为索引树很大不能一次IO读取进入内存,树的深度浅,查找数据时IO的次数也较少,效率就更快。
- B+树的每个叶子节点都指向相邻的叶子节点,构成一个有序链表,可以按照关键码排序的次序遍历全部记录。由于数据顺序排序且相连,便于去检查找和搜索。而B树的叶子节点指针为null,则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,缓存命中性没有B+树好。
Hash索引和 B+树索引优劣分析
- Hash索引定位快:Hash索引指的就是Hash表,最大的优点就是能够在短时间内,根据Hash函数定位到数据所在的位置,这个是B+树做不到的。
- Hash冲突问题:Hash最大的问题就是Hash冲突问题了,但是对于数据库来说他还不是最主要的问题。
- Hash索引最大的问题是不支持顺序和范围查询。我们有一条SQL:
select * from user where id < 500 ;
B+树是有序的。在这种范围查询中优势十分大,直接遍历比500小的叶子节点就够了,但是Hash索引是根据Hash算法来定位的,无法根据范围进行查询,难除非他要把1~499的数据都进行一次hash计算定位。
索引的类型
主键索引(Primary Key)
数据库表的主键使用的就是主键索引,通常来说一张表只能有一个主键,并且主键不能为null,且不能重复。
在MySQL的InnoDB的引擎中,当没有显示的指定表的主键的时候,InnoDB会自动检查表中是否有唯一索引的字段,如果有,则选择该字段为默认的主键,如果没有,InnoDB会自动创建一个6字节的自增主键。
二级索引(辅助索引)
二级索引又称为辅助索引,因为二级索引的叶子节点存储的数据是主键,意味着通过二级索引可以确定主键的位置。
二级索引又分为唯一索引、普通索引、前缀索引等。
- 唯一索引(Unique Key):唯一索引也是一种约束,唯一索引的属性列不能出现重复的数据,但是可以允许数据为NULL,一张表允许创建多个唯一索引。建立唯一索引的目的是为了该属性列数据的唯一性,而不是为了查询效率。
- 普通索引(Index):普通索引的唯一作用是为了快速查询数据,一张表允许创建多个普通索引,并且允许数据重复和NULL。
- 前缀索引(PreFix):前缀索引只适用于字符串类型的数据,前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。
- 全文索引(Full Text):全文索引主要是为了检索大文本数据中的关键字信息,是目前搜索引擎数据库使用的一种技术。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!