年前项目组接微信公众号。

上线之后,跟微信相关的用cid列的查询会话的SQL变慢了几十倍!思考这个问题思考了非常久。从出现以来一直是我心头的一个结。cid这一列是建了索引的,普通的cid列更新都没问题,为何仅仅有微信的有问题?同样的前缀又是怎样影响索引的?

分析过程

1.explain下微信cid的查询。微信的cid会以mid-qqwanggou001为前缀插入数据

explain

select *

from analysis_sessions

where cid = "mid-qqwanggou001-b99359d9054171901c0"

分析结果例如以下:

从explain分析能够看出。这个查询使用了索引,可是innodb觉得有165万行数据须要给mysqlserver筛选(也就是用where条件过滤)。

假设这些庞大的数据在内存,遍历一遍花不了多少时间。可是极有可能,这些数据是在磁盘上的。这么多的数据从磁盘读取然后加载内存。大量磁盘IO必定是十分的耗时的。

相比内存的电子运动。磁盘机械臂的物理运动要慢好几个数量级。2.分析普通cid的查询

取数据进行explain。cid = "sid-a2f9047ddf528d837e5f60843c83aae9"。这个数据是不带公共前缀的。

explain

select *

from analysis_sessions

where cid = "sid-a2f9047ddf528d837e5f60843c83aae9"

分析结果例如以下:

同样的列,同样的索引。这次存储引擎向mysqlserver仅仅返回了一行数据。也就是说innodb仅仅须要读取一个二级索引的叶子节点。

相对于上面那个sql的IO,压力显然小非常多。初步分析结论:带有长前缀的cid查询。innodb存储引擎会向mysql上端server返回百万级别的数据。

这仅仅是现象,我还是想问,同样的表,同样的列,同样的索引结构(B+树索引)。同样的查询,仅仅不同的数据。结果为何有差么大的区别?近一步分析纠结这个问题非常久了,直到前天晚上散步时候。无意的会想到了 explain结果的key_len这一列。这一列我从来不看,觉得没用。可是27与cid这一列50个varchar的定义格格不入。27明显小于50,首先能够肯定,这个索引用的是前缀索引,说白了,截取了字符串的前面一部分作为索引数据。analysis_session表用的gbk编码。也就是说,索引须要2个字节表示一个varchar。解释一下key_len27 = 2 * 12 + 2 + 127位的索引,仅仅索引了前面12个字符。中间的2存储长度。后面的一个字节存储Null信息,由于这一列是同意Null的。终于结论:问题到这已经非常明了了,微信cid的前缀是17个字符的,大于前缀索引的12个字符,也就是说。全部存储微信cid数据(百万级别)B+树叶子节点将仅仅有一个B+树非叶节点的指针指向这里。于是。当你查微信cid相关的数据时,全部微信cid将被返回给mysqlserver进行where过滤了,效率上讲,这是非常恐怖的。

索引确实还是被用上了。不然会造成全表扫描。可是这个数据设计的有问题。B+树的查找效率是O(LogN)的,可是遇上这个数据,立马变成O(N),相当于一个局部全表扫描。那么合理的猜測。仅仅要有新增的微信cid,微信cid的查询仅仅会变的更慢。引申,更佳的代码 practice:varchar,blob, text等边长数据建索引的时候。数据库会自己主动建前缀索引,于是B+树不会索引整个字段的部分。非常多同学喜欢用前缀作为字符串的标志,这次要注意了,有前车之鉴了。前缀存入mysql之后会减少检索效率,前缀越长。B+树查询的效率越低。这里给出代码的建议:1.将前缀作为后缀,startWith改为endWith

2.不要尝试后缀模糊搜索,like "%.com",这样的做法更糟糕,全然用不了索引,于是全表扫描。

为什么mysql查询结果有前缀_字符串的公共前缀对Mysql B+树查询影响回溯分析相关推荐

  1. 织梦数据库改mysql前缀_织梦快速批量修改MYSQL数据库表前缀与表名实例操作

    这篇文章主要为大家详细介绍了织梦快速批量修改MYSQL数据库表前缀与表名实例操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴. 我们在安装织梦系统的时候,有一次 ...

  2. mysql 多表联合查询怎么一行显示_使用 explain 优化你的 mysql 性能

    本文是关于在学习<高性能 Mysql>附录 D 中关于 Explain 如何获取执行计划信息相关总结.MySQL 提供了一个 EXPLAIN 命令,它可以对 SELECT 语句进行分析,获 ...

  3. mysql表前缀_关于数据库表前缀的认识

    mysql数据库表前缀,这个是我们区分其它表的一个方式,当我们同一个数据库中含有多个系统的的时候,表前缀就却分的唯一标识.我们使用php开源程序安装建站的时候,一般数据库表前缀都是默认设置好的,如:w ...

  4. mysql和oracle冲突吗_三分钟带你分清MySQL 和Oracle之间的误区

    原标题:三分钟带你分清MySQL 和Oracle之间的误区 来自:华为云开发者社区 摘要:MySQL和Oracle,别再傻傻分不清. MySQL 和Oracle 在开发中的使用是随处可见的,那就简单去 ...

  5. mysql触发器主机自动增长_三分钟带你分清 Mysql 和 Oracle 之间的误区

    摘要:Mysql 和Oracle,别再傻傻分不清. mysql 和Oracle 在开发中的使用是随处可见的,那就简单去了解一下这俩款火的不行的数据库. 本质区别: Oracle数据库是一个对象关系数据 ...

  6. mysql start with connect by_MYSQL实现Oracle的Start with…Connect By递归树查询

    最近接触一个老项目,最初适配的数据库是oracle 后来迁移到mysql .这个迁移是由一个已经离职的新手做的.这个新手对于很多oracle特有的函数及存储过程都没有进行迁移.导致系统很多功能都BUG ...

  7. mysql test 映射到实体_从零搭建SpringBoot+MyBatis+MySQL工程

    目录 创建工程 了解MVC模型 属性配置文件.yml springboot里的数据库布局 创建包 创建数据表 创建实体类DAO(model) 创建mapper 语句直接写在class中(全注解方式) ...

  8. LeetCode刷题记录_最长公共前缀

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...

  9. mysql设置用户永不过期_在Navicat Premium中管理MySQL用户 - 第2部分:创建新用户

    第2部分:创建新用户 在第1部分中,我们学习了如何使用Navicat Premium用户管理工具保护MySQL root帐户.本篇文章将讨论设置新用户的帐户详细信息,帐户限制和SSL设置. The G ...

最新文章

  1. halcon算子盘点:Chapter 13:对象、Chapter 14 区域
  2. initial model for Agile Development Organization: Relationship Graph
  3. maven报错解决: -source 1.5 中不支持 diamond 运算符
  4. Lintcode99 Reorder List solution 题解
  5. 爬虫结果数据完整性校验
  6. Lisenter笔记
  7. [Node.js] mySQL数据库 -- 英雄管理系统(完善)
  8. 学习结构[记录]类型(7) - 结构也可以有构造函数
  9. oracle 11g空表不能exp导出问题解决方案
  10. Eclipse创建Maven工程
  11. FreeSwitch Event Socket Command(事件套接字命令行)
  12. linux 执行文件命令
  13. 阿里大佬手把手教你用jmeter做压力测试(详图)
  14. GooglePlay内购服务器验单配置
  15. 垃圾场恶臭环境监测系统方案
  16. 数据分析中,还有哪些好用实用的方法论?
  17. 如何使用Box2D和Cocos2D制作一款像Fruit Ninja一样的游戏-第3部分
  18. 十年老程序员的职场教训,很受用
  19. python中max什么意思_Python
  20. 身体语言密码_《身体语言密码》,将个性分析应用到成功的三法则

热门文章

  1. 如何处理计算机显示器故障,显示器突然黑屏怎么办?教你这样操作,轻松解决黑屏问题!...
  2. vue实现增删改查功能
  3. 29 顺时针打印矩阵(四-画图让抽象问题形象化)
  4. zabbix-3.2 官方手册
  5. 无法远程连接阿里云的Mysql
  6. linux 查看日志
  7. (1)ActivityThread分析
  8. 转:c# 安装包制作
  9. 有关Kill Session问题的讨论(旧文初发)
  10. Win11高效日历推荐