记一次SQL调优
insert
优化
如果你在某一时刻有大量的insert
操作,一条一条插入是非常耗时的。insert
语句本身支持一次插入很多条记录,插入记录数上限受sql语句长度限制,一般一次插个几千条是没问题的。在我的 《如何手动实现Try Insert和Insert Or Update》 一文中对于各种情况都有具体的例子,这里就不赘述了。
explain
语句结果分析
SQL本身是一种对机器来说抽象级别很高的语言,我们通过SQL告诉DBMS我们需要什么,而没有告诉它具体要怎么做。DBMS会猜测性地以最优的方法去完成我们给的任务,但是它往往做得不太好,毕竟不同业务最优做法各不相同,目前我们还没有办法让机器完全理解我们的业务。所以我们需要辅助机器,帮助它找到最好的查询逻辑。通常的做法是添加合适的索引,让所有的查询都走索引。在MySQL中,在任何一个select
语句前加上explain
,就可以知道MySQL对这条查询的理解和实际执行逻辑。
下面来分析explain
语句返回的结果。explain
会展示查询涉及到的每张表分析结果,里面有很多参数,我们一般只需要关注以下几个参数:
type
type描述表是怎么
join
的,按从最好到最坏一共有以下几个值:值 解释 system 表只有一行,是一种特殊的 const
typeconst 表里只有一行匹配的记录, join
时可以认为是常量eq_ref 使用的索引为 primary key
或unique not null index
ref join
只使用最左前缀匹配原则的普通索引fulltext 使用全文检索索引 ref_or_null 与 ref
差不多,主要是多了NULL值的查询index_merge 使用了MySQL的索引合并优化 unique_subquery 类似 eq_ref
,主要用于包含IN子查询的查询range 走索引的范围查询 index 索引树被整个扫了,速度比扫表好一点 ALL 整个表被扫,非常糟糕的情况,一般要避免 一般做SQL优化,通常出现
index
和ALL
都是需要优化的。Extra
MySQL查询的附件信息,有时候代表着查询的额外代价,出现
Using filesort
、Using temperary
都表示查询速度不行。Using filesort
表示order by
子句不走索引,使用文件排序,需要对order by
进行优化。Using temperary
表示查询过程中创建了临时表,通常发生在包含group by
和order by
的查询中。
rows和filtered
rows
表示MySQL预估的查询需要的行数,filtered
表示根据条件过滤之后的行所占的百分比。值为100表示没有行被过滤掉。所以rows
*filtered
查询需要的总的行数。这个值自然是越小越好。
查询优化实践
查询优化的策略就是加索引,primary key 和 unique key在根据具体业务定,我们做优化,一般都是添加普通索引。普通索引分为两种,单个字段的索引和多个字段的联合索引。联合索引的应用场景相对窄一点,如果你要查的数据可以被联合索引全部囊括,直接从索引拿数据,可以考虑使用联合索引。读多写少重复值少散列分布的字段最适合建索引。你可以把你的程序使用到的所有SQL都列出来,一条一条explain
,没有走索引的,就酌情给某个或某几个字段(join
里的字段、where
里的字段都是重点考虑对象)加上索引,直到所有的查询走索引为止。这么做以后,你的查询type正常都可以到达比较好的情况,但是对于包含order by
子句的查询,可能你的Extra信息就不太理想了。Using filesort
和Using temperary
有时候阴魂不散,很难搞。这时候最佳的策略就是变着花样选择排序的字段。比如你的表有一个自增主键,你可以考虑用它作为插入时间来做排序。MySQL本身在这方面的优化非常糟糕,需要耐心地多尝试。
Reference
记一次SQL调优的更多相关文章
- 记一次SQL调优/优化(SQL tuning)——性能大幅提升千倍以上
好久不写东西了,一直忙于各种杂事儿,恰巧昨天有个用户研发问到我一个SQL调优的问题,说性能太差,希望我能给调优下,最近有些懒,可能和最近太忙有关系,本来打算问问现在的情况,如果差不多就不调了,那哥们儿 ...
- 记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?)
记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?) 前几天帮客户优化一个数据库,那个数据库的大小是6G 这麽小的数据库按道理不会有太大的性能问题的, ...
- SQL调优常用方法
在使用DBMS时经常对系统的性能有非常高的要求:不能占用过多的系统内存和 CPU资源.要尽可能快的完成的数据库操作.要有尽可能高的系统吞吐量.如果系统开发出来不能满足要求的所有性能指标,则必须对系统进 ...
- SQL调优
# 问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...
- 读《程序员的SQL金典》[4]--SQL调优
一.SQL注入 如果程序中采用sql拼接的方式书写代码,那么很可能存在SQL注入漏洞.避免的方式有两种: 1. 对于用户输入过滤敏感字母: 2. 参数化SQL(推荐). 二.索引 ①索引分类 聚簇索引 ...
- [SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优
最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“'1'='1'”这个表达式永远返回 true, ...
- SQL调优日志--内存问题
SQL调优日志--内存问题排查入门篇 概述 很多系统的性能问题,是由内存导致的.内存不够会导致页面频繁换入换出,IO队列高,进而影响数据库整体性能. 排查 内存对数据库性能非常重要.那么我当出现问 ...
- 读书笔记之SQL注入漏洞和SQL调优
原文:读书笔记之SQL注入漏洞和SQL调优 最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“' ...
- Oracle SQL 调优健康检查脚本
Oracle SQL 调优健康检查脚本 我们关注数据库系统的性能,进行数据库调优的主要工作就是进行SQL的优化.良好的数据架构设计.配合应用系统中间件和写一手漂亮的SQL,是未来系统上线后不出现致命性 ...
随机推荐
- DirectShow 获取音视频输入设备列表
开发环境:Win10 + VS2015 本文介绍一个 "获取音频视频输入设备列表" 的示例代码. 效果图 代码下载 代码下载(VC2015):Github - DShow_simp ...
- git查看/修改个人信息-用户名邮箱
我们在使用git作为仓库管理工具时,要设置自己Git的用户名和邮箱,要不然大家一块开发时不知道谁是谁,不知道谁提交的. 另外,当我们用自己的电脑开发时你可能设置的是一个你喜欢的昵称,所以那就得改一下. ...
- jemalloc内存占用问题
最近,有部分越南的服务器内存不断上涨,怀疑是内存泄漏,因为框架提供的内存报告里,C内存和Lua占用内存都不大,和ps里看的差好多.总内存在12G左右,C和Lua的加起来约4G,两者相差了8G 经过一番 ...
- laravel中select2多选,初始化默认选中项
项目中有发送消息功能,需要能通过搜索,多选用户,来指定发送人.使用 select2 插件来完成. select2 的 html 代码如下: <div class="form-group ...
- 转 googlenet论文解读
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u014061630/article/det ...
- 控制FlowDocumentScrollViewer滚动到最下方
原文发布于:https://www.chenxublog.com/2019/07/14/contrlo-flowdocumentscrollviewer-to-bottom.html 由于我在llco ...
- 怎么在CAD中测量图纸距离?来看看这两种方法
在CAD中设计图纸最重要的就是图纸的尺寸,俗话说也就是图纸间的距离.通过正确的数据设计出的图纸才能够准确,也能够避免施工时事不必要的误差.那怎么在CAD中测量图纸距离呢?具体要怎么来进行操作呢?下面我 ...
- node设置跨域白名单
// 判断origin是否在域名白名单列表中 function isOriginAllowed(origin, allowedOrigin) { if (_.isArray(allowedOrigin ...
- qt构建错误: dependent "*.h" does not exist.
项目中需要维护一套qt工程,今天发现一个头文件名称中单词拼写错误,就改正了,结果重新构建提示: dependent "*.h" does not exist. 原因:修改了文件后, ...
- js对象比较
使用闭包实现 js 对象按指定属性进行大小比较 需要比较的对象 let obj1 = { name:'张三', age:19 }; let obj2 = { name:'李四', age:22 }; ...