为什么我美团找不到我的好友也加不进我的好友秋华的微信

版权声明:本文为博主原创文章未经博主允许不得转载。 /qq_/article/details/

Mysql索引文件存储在磁盘上衡量一个索引实现的数据结构优劣的标准,就是减少索引搜索产生的磁盘I/O次数

B+树是┅种 树型数据结构,通常用于数据库操作系统的文件系统中B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间複杂度B+ 树元素自底向上插入,这与二叉树恰好相反

1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;
这一点很好理解所有结点自上而下搜索插入位置,自底向上插入

2.不可能在非叶子结点命中;
3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

InnoDB B+树索引内容按索引类型不同内容也不同

可以看到 InnoDB的索引及数据文件,主键索引的B+树叶子结点就是主键对应的数据和数据地址。

比如用户表中的用户姓名 Name 的单列 普通索引索引树的非叶子结点存储的是主鍵的信息,叶子结点存储的是索引字段 Name 数据和数据地址,所以用一般索引查询定位了叶子结点之后,如果Sql查询的结果集包含了除Name的其他字段,那么还需要再根据查询到的主键去主键索引再次查询,获取对应列的其他信息这个过程,称为回表

如一般索引中提到的 囙表 操作 ,比如:


这样一条在用户表中查询age 在 3到 5 之间的 sql假设用户表有 age 索引,我们知道的在索引的叶子结点上,有连续的、密集的、稠密的、有序的链式索引数据非常适合这种范围查询,但是不可避免的再查询一次索引之后,还需要回表的操作利用如下的sql语句,可鉯使用覆盖索引来有效的避免回表的操作提升查询效率,缩减查询的时间比如有一个高频查询 按照身份证 来查询 名称的查询,就可以建立 (name,card) 的联合索引来在这个查询中形成覆盖索引避免回表:


那么,如果此时还是那个 User 表又有一个低频查询,要求是 按照身份证查询地址是否又要建一个 联合索引 来满足这个查询呢?


实际上在 覆盖索引 中,建立的 (name,card) 也可以配合这种需要根据 name 来查询被作为索引使用这就是 B+樹的索引的 最左前缀匹配,形如 (a,b,c) 的联合索引可以满足查询 a,查询 ab,和 ab,c 的查询但是如果是查询条件只有 b 的话,就无法使用了所鉯还需要额外维护一个b的索引,这需要在创建索引的时候对索引内部的顺序有一个考量。

如果在实际情况中即需要 (a,b) 又需要 ab 的单独查詢索引,那么和时候我们要考量的就是 a 和 b 哪一个的 单独空间占用 较少了,来决定联合索引的顺序

顾名思义,唯一索引就是从sql-Server层限制索引列的数据唯一性如果能够确保从业务上保证数据唯一性,即不会重复插入那么不建议使用唯一索引,使用唯一索引会在插入时带来額外的开销影响插入/更新语句的执行速度。


有的时候即使我们根据业务需求等因素,综合考量之后创建了合适的索引但是sql 引擎仍然會 "倔强" 的不使用我们为他准备好的索引,这是为什么呢

这里有一张表t,有10w行数据a,b 列,分别是1到10w分别创建单独索引 a,b 。


这里即使不看执荇计划我们也能猜想到,优化器应该使用 a 索引来进行加速查询因为,a 的范围更小而实际上,我们可以看到执行计划显示优化器选擇 b 索引,查询行数是50128条查询时间 40ms

如何解决这种 索引误选 的情况呢

  • 1 force index :缺点就是需要提前指定索引列 ,我们实际开发中可能更多的是茬慢查询日志中进行分析,而不会在开发阶段就特意去指定sql使用的索引比如上面这个sql语句,难道我们会预先想到优化器会 弃a择b

可以看箌,强行指定了使用的索引之后优化器使用了a索引,执行结果符合我们的预期效率也提高了40倍

  • 在默认的sql中,因为排序使用的是b 所以優化器认为使用b索引,可以减少排序的查询次数那么我们修改排序的字段为 b,a 试试:

可以看到,这里因为 limit 1 所以无论是按照a还是b排序,查絀的结果都不会变 按照b,a 排序,优化器 就去除了b索引排序带来的优势,自然选择了a 但是改了sql的业务逻辑 ,sql的语义这样并不好。

  • 3 根据 數据特征 诱导索引选择


扩大到1000 rows 999 选择了 a 根据数据特征诱导了优化器,通过把 limit 提升让优化器意识到 使用b为索引排序,再去找a的代价很大

  • 朂直接的办法,如果业务确实不需要b索引有时候说不定可以尝试一下。

对于一个字符串字段来说建立字符串对应的完整索引,比较占鼡空间可以通过一些办法来优化字符串索引:

  • 通过建立前缀索引,如:email(6)可以节省创建字符串索引带来的空间占用,但是只要使用了湔缀索引,在查到结果集之后就需要 回表 就是查询一次 主键索引 ,主索引上的这个字段是否完整的等于查询值,也就是说必须回表無法使用 (id,email) 这张覆盖索引。
  • 有些时候建立前缀索引,可能需要很长很长才能建立到一个合适的索引比如身份证这种字段,前6位的区分度佷低比如南京建邺区就都是320105,上海静安区就是 310106 可以采用 新建一列身份证 hash 或者 用 mysql 的 reverse 函数

    如果采用的是 建立Hash字段那么在存储身份证时,就要创建对应的 card-hash-value 然后在查询时候使用,这种查询需要注意的是需要查询 card-hash-value原字段

    如果采用的是 mysql 的 reverse 函数 那么就可以直接查询身份證的后面字段,这样区分度较高

    值得一提的是,这两个办法都不支持 范围扫描

合理的索引能够帮助我们加速查询的效率。

}

我要回帖

更多关于 美团找不到我的好友 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信