💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
**1\. 什么是索引?** 索引是一种数据结构,可以帮助我们快速的进行数据的查找. ***** **2\. 索引是个什么样的数据结构呢?** 索引的数据结构和具体存储引擎的实现有关, 在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引. ***** **3\. Hash索引和B+树所有有什么区别或者说优劣呢?** 首先要知道Hash索引和B+树索引的底层实现原理: ***** hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.B+树底层实现是多路平衡查找树.对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据. 那么可以看出他们有以下的不同: * hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询. 因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围. * hash索引不支持使用索引进行排序,原理同上. * hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.AAAA和AAAAB的索引没有相关性. * hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(联合索引索引,覆盖索引等)的时候可以只通过索引完成查询. * hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低. 因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引. ***** **4\. 上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?** **聚簇索引:**将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据. **非聚簇索引:**将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引.如果没有唯一键,则隐式的生成一个键来建立聚簇索引. 在聚簇索引之上创建的索引称之为辅助索引,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引。**辅助索引叶子节点存储的不再是行的物理位置,而是主键值,辅助索引访问数据总是需要二次查找** 当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因此不用再次进行回表查询. ***** **5\. 非聚簇索引一定会回表查询吗?** 不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询. 举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询. ***** **6\. 在建立索引的时候,都有哪些需要考虑的因素呢?** 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合.如果需要建立联合索引(用多个字段建立一个索引)的话,还需要考虑联合索引中的顺序(和查询条件有关).此外也要考虑其他方面,比如防止过多的索引对表造成太大的压力(explain时会有优化分析).这些都和实际的表结构以及查询方式有关. ***** **7\. 联合索引是什么?为什么需要注意联合索引中的顺序?** MySQL可以使用多个字段同时建立一个索引,叫做联合索引.在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引. 具体原因为: MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序. 当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,,,以此类推.因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面.此外可以根据特例的查询或者表结构进行单独的调整. ***** **8\. 创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?** MySQL提供了**explain**命令来查看语句的执行计划,MySQL在执行某个语句之前,会将该语句过一遍查询优化器,之后会拿到对语句的分析,也就是执行计划,其中包含了许多信息. 可以通过其中和索引有关的信息来分析是否命中了索引,例如possilbe\_key(可能会选择的索引),key(实际选择的索引),key\_len(索引长度)等字段,分别说明了此语句可能会使用的索引,实际使用的索引以及使用的索引长度. ***** **9\. 那么在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?** * 使用不等于查询, * 列参与了数学运算或者函数 * 在字符串like时左边是通配符.类似于'%aaa'. * 当mysql分析全表扫描比使用索引快的时候不使用索引.