重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
一、MySQL数据库有几个配置选项可以帮助我们及时捕获低效SQL语句
创新互联客户idc服务中心,提供成都服务器托管、成都服务器、成都主机托管、成都双线服务器等业务的一站式服务。通过各地的服务中心,我们向成都用户提供优质廉价的产品以及开放、透明、稳定、高性价比的服务,资深网络工程师在机房提供7*24小时标准级技术保障。
1,slow_query_log
这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。
2,long_query_time
当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短。
3,slow_query_log_file
记录日志的文件名。
4,log_queries_not_using_indexes
这个参数设置为ON,可以捕获到所有未使用索引的SQL语句,尽管这个SQL语句有可能执行得挺快。
二、检测mysql中sql语句的效率的方法
1、通过查询日志
(1)、Windows下开启MySQL慢查询
MySQL在Windows系统中的配置文件一般是是my.ini找到[mysqld]下面加上
代码如下
log-slow-queries = F:/MySQL/log/mysqlslowquery。log
long_query_time = 2
(2)、Linux下启用MySQL慢查询
MySQL在Windows系统中的配置文件一般是是my.cnf找到[mysqld]下面加上
代码如下
log-slow-queries=/data/mysqldata/slowquery。log
long_query_time=2
说明
log-slow-queries = F:/MySQL/log/mysqlslowquery。
为慢查询日志存放的位置,一般这个目录要有MySQL的运行帐号的可写权限,一般都将这个目录设置为MySQL的数据存放目录;
long_query_time=2中的2表示查询超过两秒才记录;
2.show processlist 命令
SHOW PROCESSLIST显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。
各列的含义和用途:
ID列
一个标识,你要kill一个语句的时候很有用,用命令杀掉此查询 /*/mysqladmin kill 进程号。
user列
显示单前用户,如果不是root,这个命令就只显示你权限范围内的sql语句。
host列
显示这个语句是从哪个ip的哪个端口上发出的。用于追踪出问题语句的用户。
db列
显示这个进程目前连接的是哪个数据库。
command列
显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
time列
此这个状态持续的时间,单位是秒。
state列
显示使用当前连接的sql语句的状态,很重要的列,后续会有所有的状态的描述,请注意,state只是语句执行中的某一个状态,一个 sql语句,以查询为例,可能需要经过copying to tmp table,Sorting result,Sending data等状态才可以完成
info列
显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,但是一个判断问题语句的重要依据。
这个命令中最关键的就是state列,mysql列出的状态主要有以下几种:
Checking table
正在检查数据表(这是自动的)。
Closing tables
正在将表中修改的数据刷新到磁盘中,同时正在关闭已经用完的表。这是一个很快的操作,如果不是这样的话,就应该确认磁盘空间是否已经满了或者磁盘是否正处于重负中。
Connect Out
复制从服务器正在连接主服务器。
Copying to tmp table on disk
由于临时结果集大于tmp_table_size,正在将临时表从内存存储转为磁盘存储以此节省内存。
Creating tmp table
正在创建临时表以存放部分查询结果。
deleting from main table
服务器正在执行多表删除中的第一部分,刚删除第一个表。
deleting from reference tables
服务器正在执行多表删除中的第二部分,正在删除其他表的记录。
Flushing tables
正在执行FLUSH TABLES,等待其他线程关闭数据表。
Killed
发送了一个kill请求给某线程,那么这个线程将会检查kill标志位,同时会放弃下一个kill请求。MySQL会在每次的主循环中检查kill标志位,不过有些情况下该线程可能会过一小段才能死掉。如果该线程程被其他线程锁住了,那么kill请求会在锁释放时马上生效。
Locked
被其他查询锁住了。
Sending data
正在处理SELECT查询的记录,同时正在把结果发送给客户端。
Sorting for group
正在为GROUP BY做排序。
Sorting for order
正在为ORDER BY做排序。
Opening tables
这个过程应该会很快,除非受到其他因素的干扰。例如,在执ALTER TABLE或LOCK TABLE语句行完以前,数据表无法被其他线程打开。正尝试打开一个表。
Removing duplicates
正在执行一个SELECT DISTINCT方式的查询,但是MySQL无法在前一个阶段优化掉那些重复的记录。因此,MySQL需要再次去掉重复的记录,然后再把结果发送给客户端。
Reopen table
获得了对一个表的锁,但是必须在表结构修改之后才能获得这个锁。已经释放锁,关闭数据表,正尝试重新打开数据表。
Repair by sorting
修复指令正在排序以创建索引。
Repair with keycache
修复指令正在利用索引缓存一个一个地创建新索引。它会比Repair by sorting慢些。
Searching rows for update
正在讲符合条件的记录找出来以备更新。它必须在UPDATE要修改相关的记录之前就完成了。
Sleeping
正在等待客户端发送新请求.
System lock
正在等待取得一个外部的系统锁。如果当前没有运行多个mysqld服务器同时请求同一个表,那么可以通过增加--skip-external-locking参数来禁止外部系统锁。
Upgrading lock
INSERT DELAYED正在尝试取得一个锁表以插入新记录。
Updating
正在搜索匹配的记录,并且修改它们。
User Lock
正在等待GET_LOCK()。
Waiting for tables
该线程得到通知,数据表结构已经被修改了,需要重新打开数据表以取得新的结构。然后,为了能的重新打开数据表,必须等到所有其他线程关闭这个表。以下几种情况下会产生这个通知:FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE,或OPTIMIZE TABLE。
waiting for handler insert
INSERT DELAYED已经处理完了所有待处理的插入操作,正在等待新的请求。
大部分状态对应很快的操作,只要有一个线程保持同一个状态好几秒钟,那么可能是有问题发生了,需要检查一下。
还有其他的状态没在上面中列出来,不过它们大部分只是在查看服务器是否有存在错误是才用得着。
例如如图:
3、explain来了解SQL执行的状态
explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了:
例如:
explain select surname,first_name form a,b where a.id=b.id
结果如图
EXPLAIN列的解释
table
显示这一行的数据是关于哪张表的
type
这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
possible_keys
显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
key
实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句 中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len
使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数
rows
MYSQL认为必须检查的用来返回请求数据的行数
Extra
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这里可以看到的坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢
extra列返回的描述的意义
Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
Range checked for each Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
Using temporary
看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
Where used
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)
const
表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待
eq_ref
在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
ref
这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
range
这个连接类型使用索引返回一个范围中的行,比如使用或查找东西时发生的情况
index
这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)
ALL
这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免
用SQLyog来分析MySQL数据库 SOLyog的下载 安装以及使用很简单 我去了相关网站下载 它只有 K字节大小 它把两个文件(一个可执行文件 exe和一个动态链接库文件 dll)安装到C:\Program Files\SQLyog路径下 然后运行可执行文件
安装后没有必要再访问该网站了 我访问该网站是得到了一个消息 说它的域名没有设置(configured) 登记 或正在建设中 我不清楚这个问题是暂时的还是一直是这样 该软件是免费的 并且没有标志广告(banner ads) 所以它可能是一个特定的尚未最终定型的商业模型 最终可能还是要负费的
数据库 表格(table)和列树(column tree)
该程序一启动就开始询问我的登录到MySOL服务器的口令 我只需要输入我的服务器名字 用户id和登录密码 所有其它的设置都是正确的默认值 然后(当我开始其它事务 重启几次 睡了一会之后) 我重新运行该程序 这时只需要再次输入我的登录密码 该程序没有保存密码的选项 你可以认为这是该程序的一个bug 也可以说是程序的保密特性
一旦你登录之后 界面就是很值得注意 MySOL服务器上所有的数据库都显示在一个树型控件上 你只能访问你在登录时授权的那个数据库 如果你点开代表授权给你的那个数据库的树型结构 你就可以看到一系列代表表格的节点 点开表格节点后 你就可以看到一系列显示字段名的节点和另一个代表索引的节点集合
索引界面绝对是个好东东 这样你就可以CRUD查询索引和关键字了 这相对前端数据库如Microsoft Access来说是个提高 如果考虑到MySOL刚刚开始提供对主(primary)和非相关(foreign)关键字关系的支持 本程序这部分的设计是很成熟的 在右下方的面板上 有四个标签页 即 结果(Result) 消息(Message) 对象(Object)和历史(History)
有什么缺点?
我试图发现该程序的缺点 不过只发现了一个 如果你在Win Dependency Walker下运行程序的 exe文件 你会发现它引用了DLG dll文件 而DLG dll又轮流引用AppHelp 实事上 CommDlg调用AppHelp 而当AppHelp没有请求函数时 CommDlg这么做根本就是浪费资源
过于简单?
在SQLyog FAQ上 有一种观点认为该软件没有正式归档的必要 当然 FAQ(常见问题解答)本身就是一种归档 SQLyog的界面非常直观 我建议你打印一份MySOL文档(包括SQL特殊语法扩展) 我就是这么做的 它只用了一个半英寸的活页封面
最后一步?
FAQ还让人想到一个让人耳朵起了老茧却又是正确的Occam s Razor准则——一切超出必要的复杂性都是没有必要的 我之所以到处 推销 这个工具 就是因为它可以为我们提供一个可以管理MySOL服务器上许多数据库的 简单的 图形化的界面 它的速度极快 并且它的拷贝很小(可以放在一张软盘上)
lishixinzhi/Article/program/SQL/201404/30537
执行顺序:
适用结构相同的表联结成一张大表
内连接:返回两个表共同的行
左连接:以表 1 为基础,匹配表 2 的相同行
右连接:以表 2 为基础,匹配表 1 的相同行
全连接:返回全部数据,可以理解为左连接和右连接的结合
mysql 没有全连接
常用于组内排序,具体写法如下
窗口函数可以用 rank 相关函数或者聚合函数
当前日期+时间(date + time)函数:now()
当前时间戳函数:current_timestamp()
日期或时间转换为字符串 函数:date_format(date,format), time_format(time,format)
lower(str):将字符串参数值转换为全小写字母后返回
upper(str):将字符串参数值转换为全大写字母后返回
concat(str1, str2,...):将多个字符串参数首尾相连后返回
concat_ws(separator,str1,str2,...):将多个字符串参数以给定的分隔符 separator 首尾相连后返回
substr(str,pos):截取从 pos 位置开始到最后的所有 str 字符串
substr(str, pos, len):截取 str 字符串,从 pos 位置开始的 len 个字符
length(str):返回字符串的存储长度
char_length(str):返回字符串中的字符个数
format(X,D,locale):以格式 ‘#,###,###.##’ 格式化数字 X,D 指定小数位数,locale 指定国家语言(默认的 locale 为 en_US)
left(str, len):返回最左边的len长度的子串
right(str, len):返回最右边的len长度的子串
ltrim(str),rtrim(str):去掉字符串的左边或右边的空格
repeat(str, count):将字符串 str 重复 count 次后返回
reverse(str):将字符串 str 反转后返回
通俗易懂的学会:SQL窗口函数
mysql format时间格式化说明
MySQL常用字符串函数
mysql slow log 是用来记录执行时间较长(超过long_query_time秒)的sql的一种日志工具
启用 slow log
有两种启用方式:
在f 里 通过 log slow queries[=file_name]
在mysqld进程启动时 指定–log slow queries[=file_name]选项
比较的五款常用工具
mysqldumpslow mysqlsla myprofi mysql explain slow log mysqllogfilter
mysqldumpslow mysql官方提供的慢查询日志分析工具 输出图表如下:
主要功能是 统计不同慢sql的
出现次数(Count)
执行最长时间(Time)
累计总耗费时间(Time)
等待锁的时间(Lock)
发送给客户端的行总数(Rows)
扫描的行总数(Rows)
用户以及sql语句本身(抽象了一下格式 比如 limit 用 limit N N 表示)
mysqlsla 推出的一款日志分析工具(该网站还维护了 mysqlreport mysqlidxc 等比较实用的mysql工具)
整体来说 功能非常强大 数据报表 非常有利于分析慢查询的原因 包括执行频率 数据量 查询消耗等
格式说明如下:
总查询次数 (queries total) 去重后的sql数量 (unique)
输出报表的内容排序(sorted by)
最重大的慢sql统计信息 包括 平均执行时间 等待锁时间 结果行的总数 扫描的行总数
Count sql的执行次数及占总的slow log数量的百分比
Time 执行时间 包括总时间 平均时间 最小 最大时间 时间占到总慢sql时间的百分比
% of Time 去除最快和最慢的sql 覆盖率占 %的sql的执行时间
Lock Time 等待锁的时间
% of Lock %的慢sql等待锁时间
Rows sent 结果行统计数量 包括平均 最小 最大数量
Rows examined 扫描的行数量
Database 属于哪个数据库
Users 哪个用户 IP 占到所有用户执行的sql百分比
Query abstract 抽象后的sql语句
Query sample sql语句
除了以上的输出 官方还提供了很多定制化参数 是一款不可多得的好工具
mysql explain slow log 德国人写的一个perl脚本
功能上有点瑕疵 不仅把所有的 slow log 打印到屏幕上 而且统计也只有数量而已 不推荐使用
mysql log filter google code上找到的一个分析工具 提供了 python 和 php 两种可执行的脚本
log filter/
功能上比官方的mysqldumpslow 多了查询时间的统计信息(平均 最大 累计) 其他功能都与 mysqldumpslow类似
特色功能除了统计信息外 还针对输出内容做了排版和格式化 保证整体输出的简洁 喜欢简洁报表的朋友 推荐使用一下
myprofi 纯php写的一个开源分析工具 项目在 sourcefe 上
功能上 列出了总的慢查询次数和类型 去重后的sql语句 执行次数及其占总的slow log数量的百分比
从整体输出样式来看 比mysql log filter还要简洁 省去了很多不必要的内容 对于只想看sql语句及执行次数的用户来说 比较推荐
总结
工具/功能 一般统计信息 高级统计信息 脚本 优势 mysqldumpslow 支持 不支持 perl mysql官方自带 mysqlsla 支持 支持 perl 功能强大 数据报表齐全 定制化能力强 mysql explain slow log 支持 不支持 perl 无 mysql log filter 支持 部分支持 python or php 不失功能的前提下 保持输出简洁 myprofi 支持 不支持 php 非常精简
lishixinzhi/Article/program/MySQL/201311/29428
我们先来看第一个阶段,MySQL慢的诊断思路,一般我们会从三个方向来做:
第一个方向是MySQL内部的观测
第二个方向是外部资源的观测
第三个方向是外部需求的改造
1.1 MySQL 内部观测
我们来看MySQL内部的观测,常用的观测手段是这样的,从上往下看,第一部分是Processlist,看一下哪个SQL压力不太正常,第二步是explain,解释一下它的执行计划,第三步我们要做Profilling,如果这个SQL能再执行一次的话, 就做一个Profilling,然后高级的DBA会直接动用performance_schema ,MySQL 5.7 以后直接动用sys_schema,sys_schema是一个视图,里面有便捷的各类信息,帮助大家来诊断性能。再高级一点,我们会动用innodb_metrics进行一个对引擎的诊断。
除了这些手段以外,大家还提出了一些乱七八糟的手段,我就不列在这了,这些是常规的一个MySQL的内部的状态观测的思路。除了这些以外,MySQL还陆陆续续提供了一些暴露自己状态的方案,但是这些方案并没有在实践中形成套路,原因是学习成本比较高。
1.2 外部资源观测
外部资源观测这部分,我引用了一篇文章,这篇文章的二维码我贴在上面了。这篇文章是国外的一个神写的,标题是:60秒的快速巡检,我们来看一下它在60秒之内对服务器到底做了一个什么样的巡检。一共十条命令,这是前五条,我们一条一条来看。
1.uptime,uptime告诉我们这个机器活了多久,以及它的平均的负载是多少。
2.dmesg -T | tail,告诉我们系统日志里边有没有什么报错。
3.vmstat 1,告诉我们虚拟内存的状态,页的换进换出有没有问题,swap有没有使用。
4. mpstat -P ALL,告诉我们CPU压力在各个核上是不是均匀的。
5.pidstat 1,告诉我们各个进程的对资源的占用大概是什么样子。
我们来看一下后五条:
首先是iostat-xz 1,查看IO的问题,然后是free-m内存使用率,之后两个sar,按设备网卡设备的维度,看一下网络的消耗状态,以及总体看TCP的使用率和错误率是多少。最后一条命令top,看一下大概的进程和线程的问题。
这个就是对于外部资源的诊断,这十条命令揭示了应该去诊断哪些外部资源。
1.3 外部需求改造
第三个诊断思路是外部的需求改造,我在这里引用了一篇文档,这篇文档是MySQL的官方文档中的一章,这一章叫Examples of Common Queries,文档中介绍了常规的SQL怎么写, 给出了一些例子。文章的链接二维码在slide上。
我们来看一下它其中提到的一个例子。
它做的事情是从一个表里边去选取,这张表有三列,article、dealer、price,选取每个作者的最贵的商品列在结果集中,这是它的最原始的SQL,非常符合业务的写法,但是它是个关联子查询。
关联子查询成本是很贵的,所以上面的文档会教你快速地把它转成一个非关联子查询,大家可以看到中间的子查询和外边的查询之间是没有关联性的。
第三步,会教大家直接把子查询拿掉,然后转成这样一个SQL,这个就叫业务改造,前后三个SQL的成本都不一样,把关联子查询拆掉的成本,拆掉以后SQL会跑得非常好,但这个SQL已经不能良好表义了,只有在诊断到SQL成本比较高的情况下才建议大家使用这种方式。
为什么它能够把一个关联子查询拆掉呢?
这背后的原理是关系代数,所有的SQL都可以被表达成等价的关系代数式,关系代数式之间有等价关系,这个等价关系通过变换可以把关联子查询拆掉。
上面的这篇文档是一个大学的教材,它从头教了关于代数和SQL之间的关系。然后一步步推导怎么去简化这句SQL。
第一,MySQL本身提供了很多命令来观察MySQL自身的各类状态,大家从上往下检一般能检到SQL的问题或者服务器的问题。
第二,从服务器的角度,我们从巡检的脚本角度入手,服务器的资源就这几种,观测手法也就那么几种,我们把服务器的资源全部都观察一圈就可以了。
第三,如果实在搞不定,需求方一定要按照数据库容易接受的方式去写SQL,这个成本会下降的非常快,这个是常规的MySQL慢的诊断思路。