Mysql索引在开发工作中经常用到,在此总结一些关于mysql索引的一些学习笔记
1mysql索引的本质是什么?
mysql索引的本质是分散存储的数据结构。索引达到的目的是为了快速检索,检索使用数据结构达到快速检索的目的。
2工作机制是什么?
按照相应的key在某一种数据结构中查找存储的指针,去指针指向的地址获取到相应的数据。
3哪些数据结构适合作为索引?
首先查询效率要高,查询效率高的数据结构首选hash,查询效率可以达到O(1),为什么呢?hash表的物理存储就是一个数据,我们根据key计算出数组下标,就可以在数组中快速找到需要的key和value。既然hash的查询效率这么高,mysql索引是不是hash实现的呢?不是,mysql索引查询效率只是其中一方面,还有一个重要的条件需要满足,那就是支持范围查询。显然这是hash所不支持的。
找支持范围查找的数据结构,包含二叉查找树,二叉平衡树,红黑树,B树,B+树。
其中,二叉查找树,查询效率O(lg2n),支持范围查询;mysql大部分数据插入按照主键自增的方式,这种插入方式使得二叉查找树退化为了链表的形式。
这种结构在查询的时候效率会大大被降低;二叉查找树能够退化成链表,选择能够自动平衡的树呢?红黑树,可以自身调节进行二叉树的平衡,但红黑树也有 右倾的可能,降低查询效率。
AVL树,可以避免上面所列数据结构所出现的缺点;AVL要作为mysql索引,缺点体现在哪方面呢?一是树高的问题,mysql索引是存储在磁盘上的,每获取一次节点就要进行一次磁盘IO操作。对于mysql来说,磁盘io是其性能瓶颈,所以获取数据要尽可能少地进行磁盘io。二是一个节点存储一个数据,而内存每次磁盘IO获取的数据是以页为单位(4kb),这样每次获取4kb数据,使用的到却很少,造成了一种浪费。没有利用好系统和磁盘的交互特性
从innodb索引结构分析, 为什么索引的key长度不能太长?
key太长会导致一个页当中能够存放的key的数目变少,间接导致索引树的页数目变多,索引层次增加,从而影响整体查询变更的效率。
聚集索引和非聚集索引
聚集索引是主键索引,非聚集索引是非主键创建的索引;聚集索引叶子节点存储的是表中的数据,非聚集索引叶子节点存放的是主键和索引列,使用非聚集索引查询数据时,拿到主键再去主键索引上查找想要查询的数据。
按照锁的粒度进行分类,分为两大类:
表锁:
锁的粒度大,发生冲突概率高,并发度低,加锁快,开销小。
行锁:
锁的粒度小,发送冲突概率低,并发度高,加锁慢,开销大。
Innodb行锁表锁都支持,MyISAM只支持表锁;Innodb通过索引条件时使用行级锁,否则使用表锁。
表锁分为两种模式:表读锁,表写锁;总结为 读读不阻塞,读写阻塞,写写阻塞。
Innodb实现的行锁:
共享锁(S锁):
允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁;也叫做读锁:读锁是共享的,多个客户可以同时读取同一个资源,但不允许其他客户修改。
排他锁(X锁):
允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。也叫做写锁:写锁是排他的,写锁会阻塞其他的写锁和读锁 。
悲观锁:
select语句后加了for update 相当于加了排它锁,其他的事务就不能对它修改了,需要等待当前事务修改完后才能修改。
乐观锁:
乐观锁不是数据库层面上的锁,需要自己手动去加的锁,本身不对数据加锁而是通过业务实现加锁的功能。
死锁:
并发情况下少不了死锁,死锁无法完全避免,可以尽量通过一些操作避免死锁:
为表添加合理的索引:不走索引,会为每一行记录添加上锁,死锁概率增大。
大事务拆小:大事务更倾向于死锁。
降低隔离级别:业务允许,可以降低隔离级别。
固定顺序访问表:避免交叉等待锁的情形。