3.3.3、更改数据时索引的变化
UPDATE `zz_user` SET name = "狗熊" WHERE ID = 6;
复制代码
对于上述这条修改语句,索引维护的过程相信大家自己也能推测出来,毕竟修改的本质就是先删再插入,首先在聚簇索引上查到ID=6这条数据,获取原本的name字段值:“棕熊”,然后以该值去非聚簇索引上找到对应的索引信息,然后将这个索引信息删除掉,紧接着再插入一个“狗熊”的索引信息。
当非聚簇索引更新完成后,紧接着会去更新聚簇索引,聚簇索引就不会删数据了,因为聚簇索引上保存着行数据。
首先会在聚簇索引上根据ID=6找到对应的行数据,然后将行数据中的name字段更新为“狗熊”。
至此,对于写SQL执行后,索引的维护过程就做了简单分析,实际上也并不难。
PS:实际索引更新数据时,具体的过程也会复杂一些,会牵扯到锁机制,也包括会判断修改的新值与原值的大小,如果大小相同则直接在原空间做修改(直接插入覆盖),如果不同才会先删再改。
3.4、主键为何推荐使用自增整数ID?
我曾推荐大家使用自增的整数ID作为主键,而并不是使用随机的UUID这类字符串等类型,这是为何呢?因为观察前面name索引字段的插入过程,能够很明显的观察到一个现象,字符串是无序的,当使用字符串作为主键字段时,在插入数据的时候会频繁破坏原有的树结构,造成树分裂以及后续节点的挪动,一两个条数据插入倒还没关系,但是每一条插入的数据都有可能导致树的结构调整一次,这个过程的开销可想而知.....
但是自增的整数ID就不会有这个问题,因为插入的ID本身就是按序递增的,因此插入的每一条新数据,都会直接放到B+Tree最后的节点中存储。
同时,除开上述原因外,还有一个原因就是UUID比整数自增ID长,UUID至少占位32字节,但int类型只占4字节,存储一个UUID的空间,可以存8个自增整数ID。也就代表着单个节点中,能存储的自增ID会比UUID多很多,单个节点存储的索引键越多.....(后面这一排就不讲了,前面复述过两次了,大家应该也懂哈~)
四、索引原理篇总结
到目前而言,对于MySQL的索引底层实现,大多数内容就全面讲明白了,从最开始的全表扫描过程,到磁盘IO实现、局部性原理、索引为什么默认是B+Tree结构、建立索引后发生的一系列事情、写类型的SQL对索引的影响.....等一系列内容进行了深入剖析。
聚簇索引和非聚簇索引的根本区别:
- 聚簇索引中,表数据和索引数据是按照相同顺序存储的,非聚簇索引则不是。
- 聚簇索引在一张表中是唯一的,只能有一个,非聚簇索引则可以存在多个。
- 聚簇索引在逻辑+物理上都是连续的,非聚簇索引则仅是逻辑上的连续。
- 聚簇索引中找到了索引键就找到了行数据,但非聚簇索引还需要做一次回表查询。
InnoDB-非聚簇索引与MyISAM-非聚簇索引的区别:
- InnoDB中的非聚簇索引是以聚簇索引的索引键,与具体的行数据建立关联关系的。
- MyISAM中的非聚簇索引是以行数据的地址指针,与具体的行数据建立关联关系的。
一般来说,由于MyISAM引擎中的索引可以根据指针直接获取数据,不需要做二次回表查询,因此从整体查询效率来看,会比InnoDB要快上不少。