前言:
数据库的索引一直是后端面试的高频考点,今天总结一下,如有不足,敬请指正。
基础知识:磁盘预读(预读的长度一般为页的整数倍)
页是存储的逻辑块,操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(许多操作系统中,页大小统称为4k),主存和磁盘以页为单位交换数据。
问题一:索引的基本原理是什么?
索引:Mysql官方对索引的定义为:索引
是帮助Mysql高效 的获取数据的一种数据结构,它的本质时一种数据结构。
索引就是用来快速地寻找那些具有特定值的记录。如果没有索引,一般来说执行查询时会遍历整张表。
索引的原理:就是把无序的数据变成有序的查询
。
例如:一本字典 他有按笔画查询、按拼音查询、按部首查询,这些就相当于是索引,如果没有这些,我们在查询的时候是无序的,当有了这些索引之后,在查询的而过程中,会根据特定的索引按顺序依次查询自己想要的。
- 把创建了索引的列的内容进行排序
- 对排序结果生成倒排表
- 在倒排表内容上拼上数据地址链
- 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
问题二:mysql存储索引时数据结构的选择
1.可以使用hash表这个数据结构
当存储的时候,存储引擎都会为索引列计算一个哈希码,根据哈希码,匹配出hash表中存储的具体位置,然后数据就放在这个索引的下方,哈希表中保存指向每个数据行的指针。当两个哈希值相同的时候,会采取链表进行哈希冲突的解决,类似于hashmap。因为索引的结构是十分紧凑的,所以查询非常快。
hash索引的优点:
在等值查询的时候,hash索引具有绝对优势,因为经过一次Hash算法即可找到相应的键值,复杂度为O(1),这个前提是键值都是唯一的。
如果键值不唯一,即存在hash冲突,就需要先找到该键所在的位置,然后再根据链表往后扫描,直到找到对应的数据,这时候复杂度是O(n),降低了Hash查找的效率。
所以,Hash 索引通常不会用到重复值多的列上,比如列为性别、年龄的情况等
缺点:
利用hash存储的话需要将所有的数据文件添加到内存,比较耗费内存空间
2.二叉树和红黑树
无论是二叉树还是红黑树,都会因为树的深度过深而造成io次数变多,进而影响数据读取的效率
3.B树
4.B+树
问题三:如何通过索引优化
索引的用处:
- 快速查找匹配WHERE子句的行
- 如果表具有多列索引,则优化可以使用索引的任何最左前缀来查找行
- 当有表连接的时候,从其他表检索行数据
- 查找特定索引列的min或者max
- 如果排序或分组时可用索引的最左前缀上完成的,则对表进行排序和分组
索引的分类:
主键索引 唯一索引 普通索引 全文索引 组合索引
1、创建索引
对于查询占主要的应用来说,索引显得尤为重要。很多时候性能问题很简单的就是因为我们忘了添加索引而造成的,或者说没有添加更为有效的索引导致。如果不加索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。
2、复合索引
比如有一条语句是这样的:select * from users where area=‘beijing’ and age=22;
如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age, salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
3、索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
4、使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
5、排序的索引问题
mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。