MySQL查询性能优化一则
公司有一套Web系统, 使用方反馈系统某些页面访问速度缓慢, 用户体验很差, 并且偶尔还会出现HTTP 502错误。
这是典型的服务器端IO阻塞引发的问题,通过对访问页面的程序逻辑进行跟踪,发现问题应该是出在某个SQL查询上。
在页面程序运行的某个步骤中,有这样一段SQL
select distinct(server) from user_record where type = 'GD0001'
user_record表中的数据大概有2000万条左右 , 字段type的值为GD0001的记录大概有500万,而这段SQL执行的结果大概有30多条。type字段上有索引,但是SQL语句的执行时间却要超过一分钟。
得到去重后server字段的值是导致页面访问缓慢的根本原因。
根据程序的要求, server字段的值需要实时求得,所以当初在设计程序的时候才会使用这段SQL去获得结果。数据量少的时候,不会出现问题,然而, 数据增长的速度超出当初的预期,于是就导致了性能问题的出现。
要解决这个问题不难,因为server字段值的范围相对是稳定的,可以想办法把值提取出来放到一个冗余的表里面,并且通过某种机制让这个新表的值与原表中server字段的值保持同步,查的时候查这个新表, 这样访问速度缓慢的问题也就迎刃而解了。
显然,使用这种方案解决问题需要不小的工作量。要使解决这个问题的成本最小化,最好的方法是优化这个查询,假如原本这个查询运行的时间是一分钟,那么能使运行这个查询的时间下降至一秒,问题也算解决。
这个目标看起来似乎难以实现,事实上却是可以做到的。
select distinct(server) from user_record where type = 'GD0001'
因为这段SQL语句的筛选条件type字段有索引,所以整个SQL语句的逻辑查询步骤大致如下
通过type索引筛选出符合要求记录的主键字段的标识
通过主键标识定位到表中记录的源数据
拿到字段的值进行distinct去重得到最终的结果。
上面的三个步骤中,最消耗性能的是第二步。因为索引和表的实际数据其实是分开放置的,大概的样子如下面这个图。图中长的最大的那个其实就是数据表,表中所有的数据都在上面,只是看起来不像一张“表”而已。

第二步是通过索引筛选出符合条件的记录的主键标识定位到实际数据,过程大概如下面这张图

想象一下, 要优化的那段SQL,而type值为GD0001记录有500万条, 就算MySQL不会蠢到去查500万次才能得到结果,但也肯定不是轻轻松松就能完成的。 如果能优化掉这一步,整个查询的开销也就下去了。
select distinct(server) from user_record where type = 'GD0001'
对于这段SQL,我们的目标是并不是得到所有字段的值,仅仅server字段的值就足够了。
假如我们把server字段的值放在type字段的索引里,那么在第一步查索引的时候就能得到第二步的结果。执行过程如下图

在关系数据库中,有一种索引称为覆盖索引,就是为了满足这种优化需求而设计的。
针对这段SQL语句优化的覆盖索引创建语句如下
create index index_type_server on user_record(type, server)
这个索引创建语句会将type和server两个字段的值组织在一个索引里面, 因此当
select distinct(server) from user_record where type = 'GD0001'
所有的查询步骤在索引中就能完成,而不用再去源数据表里提取数据,也就是在没建立这个索引时进行查询的第二步被消除了,因此查询的性能极大幅度的得到了提升。
在没建立覆盖索引前,查询的时间需要一分钟以上,在建立索引后,查询的时间下降到几百毫秒的级别。原本网页加载缓慢和偶尔报HTTP 502错误失去响应的问题也得到了解决。
让SQL语句合理的利用索引快速的得到查询结果是一门学问,值得深究。 合理利用索引,能让对程序性能的优化从代码层面转移到数据库层面, 让问题由最适合解决的工具和手段去解决,物尽其用,如此不但能减少代码复杂度,还能提高解决问题的效率。这是一个程序员必须要具备的一种技能。
延伸阅读:http://www.cnblogs.com/aspwebchh/p/6652855.html
原文链接:https://www.chhblog.com/article_view?id=385
MySQL查询性能优化一则的更多相关文章
- MySQL查询性能优化(精)
MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...
- 170727、MySQL查询性能优化
MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...
- 到底该不该使用存储过程 MySQL查询性能优化一则
到底该不该使用存储过程 看到<阿里巴巴java编码规范>有这样一条 关于这条规范,我说说我个人的看法 用不用存储过程要视所使用的数据库和业务场景而定的,不能因为阿里巴巴的技术牛逼,就视 ...
- MySQL查询性能优化七种武器之索引下推
前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下: MySQL查询性能优化七种武器之索引潜水 MySQL查询性能优化七种武器之链路追踪 今天要讲的是MySQL的另一种查询性能优化方式 ...
- MySQL优化技巧之五(mysql查询性能优化)
对于高性能数据库操作,只靠设计最优的库表结构.建立最好的索引是不够的,还需要合理的设计查询.如果查询写得很糟糕,即使库表结构再合理.索引再合适,也无法实现高性能.查询优化.索引优化.库表结构优化需要齐 ...
- MySQL查询性能优化---高性能(二)
转载地址:https://segmentfault.com/a/1190000011330649 避免向数据库请求不需要的数据 在访问数据库时,应该只请求需要的行和列.请求多余的行和列会消耗MySql ...
- 《高性能MySQL》之MySQL查询性能优化
为什么查询会慢? 响应时间过长.如果把查询看做是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上优化其子任务,要么消除其中一些子任务,要么减少子任务的执行次数, ...
- mysql查询性能优化
mysql查询过程: 客户端发送查询请求. 服务器检查查询缓存,如果命中缓存,则返回结果,否则,继续执行. 服务器进行sql解析,预处理,再由优化器生成执行计划. Mysql调用存储引擎API执行优化 ...
- MySQl 查询性能优化相关
0. 1.参考 提升网站访问速度的 SQL 查询优化技巧 缓存一切数据,读取内存而不是硬盘IO 如果你的服务器默认情况下没有使用MySQL查询缓存,那么你应该开启缓存.开启缓存意味着MySQL 会把所 ...
- Mysql 查询性能优化
查询优化,索引优化,库表结构优化需要齐头并进,一个不能落. 为什么查询速度会慢 在阐释编写快速的查询之前,需要清楚一点,真正重要的是响应时间.如果把查询看做是一个任务的话,那么它由一系列子任务构成,每 ...
随机推荐
- Python中的单例模式的几种实现方式的优缺点及优化
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- jQuery 数据操作函数(九)
.clearQueue() 从队列中删除所有未运行的项目. .data() 存储与匹配元素相关的任意数据. jQuery.data() 存储与指定元素相关的任意数据. .dequeue() 从队列最前 ...
- MssqlOnLinux 备份和日志【3】
数据库恢复模式: 一 简单模式:只对数据进行备份,不备份日志. 二 完整模式:支持数据,日志备份. 三 大容量日志模式:支持数据,日志备份.适用于大规模大容量操作,用最小的方式记录大多数操作. 数据库 ...
- 如何利用git shell提交代码到github
在很早之前我根据找到的一些资料以及自己的实践总结了一篇如何将VS2015上的代码上传到GitHub上,后来我发现有小伙伴私信我,说跟我上面写的不一样,但是那段时间也比较忙,当我发现有人私信的时候差不过 ...
- java数据结构与算法(一)
1.数据结构概念 所谓的数据结构是数据之间的关系,都是为了提高程序效率而设计的. 分为逻辑关系和物理关系两种. 逻辑关系:人为的一种逻辑思维的认为. (1)集合:在一个范围内有多个数据,数据之间没有关 ...
- 详说 Navicat for MySQL 快捷键
详说 Navicat for MySQL 快捷键: Navicat 主窗口 Navicat 主窗口快捷键 常规 Navicat 常规快捷键 表设计器 Navicat 表设计器快捷键 表查看器 Navi ...
- Vue 组件之 Router
Vue 组件之 Router Vue 开发单页应用的时候,免不了使用Vue组件.在单页应用上如何进行组件切换? 结构如下图所示: 主页面包含Foo组件与Bar组件,在主页面中可以进行Foo与 Bar的 ...
- 【Java学习笔记之十七】Java中普通代码块,构造代码块,静态代码块区别及代码示例分析
//执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 //普通代码块:在 ...
- 【转载】Java 内存分配全面浅析
本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 本文转载自袭烽大神的博客,原文链接 ...
- HDU 1012 u Calculate e【暴力打表,水】
u Calculate e Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...