MySQL程序剖析 (Profiling)
我们将要详细的讲到MySQL的剖析(Profiling),因为它很少依赖于你的应用。应用和服务器 级别的剖析有的时候都是有必要的。虽然应用级别的剖析可以给你整个应用性能的总揽。,但是对MySQL的剖析提供了信息是服务器级别所提供不了的。比如, 对PHP代码进行剖析不会显示MySQL有多少行语句执行了。
与应用剖析一样,目标是找出MySQL哪部分消耗过多的时间。我们不会剖析MySQL源码的,虽然有的 时候定制化MySQL安装很有用,但是这是另一本书的主题了。所替代的是,我们将教你一些可以技术来获取和分析不同种类的MySQL执行语句的信息。
你可以用在任意的颗粒级别以满足你的需求:你可能对整个服务器进行剖析或者单独检查一个语句或者一组语 句。下列信息你可以一点点的收集:
- MySQL经常访问的那些数据
- MySQL经常执行语句的类型
- MySQL线程大部分时间的状态
- MySQL经常执行语句的子系统
- MySQL执行语句所访问的数据类型
- 不同活动的类型,比如扫描索引。
我们先从范围最广的剖析开始,那就是服务器剖析,将教你更多细节。
记录执行的语句
MySQL有两种记录语句的类型:general log和slow log。他们都是记录执行语句,但是却在语句执行进程的两端。general log记录了每个服务器收到的语句,因此它的语句可能包含了那些没有执行导致错误的语句。general Log记录了所有的语句,包括了一些非执行语句的事件,比如连接和断开连接。你可以用一个指令来启用它。
log =
根据设计,general log不会包括执行时间和其他一些仅仅在语句执行完毕的信息。相比较而言,slow log记录执行完毕的语句。尤其是,它记录那些超过指定时间执行的语句。这两种日志都对程序剖析很有用,但是slow log是获取问题语句的主要工具。我们常常推荐把它开启。
下面列出的配置会开启这个日志。获取所有执行时间超过2s的语句,以及记录那些不使用索引的语句。它也 会记录一些执行慢的管理语句,比如OPTIMIZE TABLE:
log-slow-queries =
long_query_time = 2
log-queries-not-using-indexes
log-slow-admin-statements
你可以自定义这些配置,然后把它们放到my.conf文件中。更多的服务器配置将在以后的章节详细讲 述。
long_query_time的默认值是10s。这个设置太慢了,因此我们一般都设置它为2s。然 而,对于许多应用,可能1s都非常慢了。我们在下一部分将讲述如何获得颗粒度更细的日志。
在MySQL5.1中,提供了运行时调整 slow_query_log,slow_query_log_file参数来控制slow log.但是在MySQL5.0中,在不启动MySQL的情况下,不能开闭slow log。对于MySQL5.0的变通方法是,可以动态的修改long_query_time变量。下面的语句虽然不是真正开启slow log的方式,但是取得了同样的效果。(如果有语句执行超过了10000s,那么你需要优化了这些语句了)
mysql> SET GLOBAL long_query_time = 10000;
相关配置变量,log_queries_not_using_indexes 使服务器记录没有使用索引的语句。而不管它们的执行时间。虽然开启了slow log会增加一些时间的消耗,导致语句执行速度减慢,但是没有使用索引的语句还是可以经常和非常快速的执行。(比如一些查询一些数据量小的表)这样会使降 低服务器的速度,以及使用大量的硬盘空间保存日志。
不幸的是,在MySQL5.0中不能动态的开启或关闭日志。你必须修改MySQL配置文件,然后重启 MySQL。当你想关闭日志而不想重启服务器,可以把日志文件做一个/dev/null的指向。在确定了MySQL关闭了日志文件描述以及在/dev /null重新打开它,那么你仅执行FLUSH LOGS就可以了。
相比较而言,MySQL5.1能实时更改日志以及能把日志记录到表中。这是个很大的进步了。
细颗粒度的日志
MySQL5.0以及更早的版本的slow log 都有一定的限制,在一些用途下就没用了。最首要的问题就是它的颗粒度仅仅是秒。以及long_query_time在MySQL5.0中最小单位就是 1s。大部分交互的应用中,这个时间就比较长了。如果你正在开发一个高性能的WEB应用,你可能希望整个页面生成小于1s.以及在开始生成的过程中记录许 多语句。这种情况下,一个语句执行了150ms,也会被认为是个很慢的语句。
另一个问题是,并不是所有的执行语句都记录在slow log中(尤其是,子节点的线程语句不能被记录)。general log记录了所有的语句,但是是在这些语句解析之前记录的,只要就不能记录一些如执行时间,锁时间,以及执行的行数的记录了。只有slow log包含这些信息。
最终,如果你开启了log_queries_not_using_indexes参数。可能slow log就被大量的实体,高效的语句所填满。比如,如果你过你生成一个下拉菜单的数据,你可能执行SELECT * FROM STATES。这个语句就被记录了,因为它是整张表的扫描。