JavaGuide八股文
MySQL 索引详解open in new window
索引是一种用于快速查询和检索数据的数据结构,其本质可以看成是一种排序好的数据结构。
索引的作用就相当于书的目录。打个比方: 我们在查字典的时候,如果没有目录,那我们就只能一页一页的去找我们需要查的那个字,速度很慢。如果有目录了,我们只需要先去目录里查找字的位置,然后直接翻到那一页就行了。
优点 :
缺点 :
但是,使用索引一定能提高查询性能吗?
大多数情况下,索引查询都是比全表扫描要快的。但是如果数据库的数据量不大,那么使用索引也不一定能够带来很大提升。
创建索引
## 在user表上对id属性添加索引user_index
CREATE INDEX user_index
ON user (id);
添加索引) 添加索引
## 修改表 在user表的添加对id属性的索引user_index
ALTER table user ADD INDEX user_index(id)
创建唯一索引) 创建唯一索引
CREATE UNIQUE INDEX user_index ## UNIQUE关键字表示该索引是唯一索引
ON user (id);
删除索引) 删除索引
ALTER TABLE user
DROP INDEX user_index; ## DROP语句删除索引
为什么不使用Hash表:
SELECT * from table1 WHERE id < 500
如果在该例子内使用的是Hash表数据结构的话,那么我们需要对id处于1-499 内的索引进行一次Hash计算查找出对应的index,这样的话十分死板浪费资源时间。如果在该场景下使用B+树的话,直接遍历id < 500 的叶子节点就可以得到查询结果,这样的话就比较节省时间
B树与B+树:
B树也称 B-树,全称为 多路平衡查找树 ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 Balanced
(平衡)的意思
之间的区别:
主键索引:
一张表只能有一个主键,该主键的值不能为null不能重复,根据该主键构建的索引就为主键索引
if 存在主键
then 创建主键索引
else if 不存在主键
then 表内查找唯一索引并不允许null值的字段,设置为默认主键,创建主键索引
else then 自动创建一个6字节的自增主键
二级索引:
二级索引(Secondary Index)又称为辅助索引,是因为二级索引的叶子节点存储的数据是主键。也就是说,通过二级索引,可以定位主键的位置
二级索引包括:唯一索引、前缀索引、普通索引
概念:
聚簇索引(聚集索引):索引结构和数据一起存放的索引,InnoDB 中的主键索引就属于聚簇索引。
非聚簇索引(非聚集索引):索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引
各自索引的优缺点:(有点像数组与链表之间的区别)
优点:
1.查询速度很快
2.排序查找与范围查找速度很快
缺点:
1.构建的数据需要是有序的数据
2.索引数据如果被修改的话,更新的代价比较大
优点:
1.更新代价比聚簇索引小
缺点:
1.依赖于有序的数据
2.有可能会出现二次查询(回调) (最大缺点)
回调:
当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。
选择合适的字段:
频繁更新的字段应该慎重建立索引:
虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了
限制每张表上的索引数目:
索引并不是越多越好,建议单张表索引不超过 5 个!索引可以提高效率同样可以降低效率。
索引可以增加查询效率,但同样也会降低插入和更新的效率,甚至有些情况下会降低查询效率。
因为 MySQL 优化器在选择如何优化查询时,会根据统一信息,对每一个可以用到的索引来进行评估,以生成出一个最好的执行计划,如果同时有很多个索引都可以用于查询,就会增加 MySQL 优化器生成执行计划的时间,同样会降低查询性能。
尽量建立联合索引而不是单列索引:
因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升
注意避免亢余索引:
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引
删除长期未使用的索引:
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引