随笔 - 6  文章 - 0 评论 - 2 阅读 - 4456
< 2025年4月 >
30 31 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 1 2 3
4 5 6 7 8 9 10

MySQL单条SQL语句性能评估

-基于《High Performance MySQL》第五章Profiling a Single Query

很不幸,大部分MySQL指令对于评估一条SQL语句都不是很给力。虽然MySQL在这方面正在努力,不过目前为止,实际最好用的只有这两个命令:SHOW STATUS和SHOW PROFILE。

SHOW PROFILE命令

这个命令来自社区贡献,由Jeremy Cole提供,集成到了5.1以后的版本中。默认是没有开启这个命令支持的,需要用SET profiling = 1;来开启。开启以后,会输出任何命令的耗时和执行过程中的状态变化。每次执行命令的时候,评估数据会被记录到一个临时表中,这个表可以通过SHOW PROFILES;来看:

clip_image002

接着可以 SHOW PROFILE FOR QUERY 1;

clip_image004
评估表保存了SQL语句执行的每一步子过程耗时。这样直接从头到尾列出来不是很容易发现问题,可以用SQL计算做一个计算:

>SET @query_id = 1;

>SELECT STATE, SUM(DURATION) AS Total_R,

ROUND(
-> 100 * SUM(DURATION) /
-> (SELECT SUM(DURATION)
-> FROM INFORMATION_SCHEMA.PROFILING
-> WHERE QUERY_ID = @query_id
-> ), 2) AS Pct_R,
-> COUNT(*) AS Calls,
-> SUM(DURATION) / COUNT(*) AS "R/Call"
-> FROM INFORMATION_SCHEMA.PROFILING
-> WHERE QUERY_ID = @query_id
-> GROUP BY STATE
-> ORDER BY Total_R DESC;

得到:

clip_image006

这样更容易发现最耗时的操作并针对性得调整SQL语句。有些过程比如"Sending Data",很难对应到具体如何优化,因为每一步操作基本都会涉及到发送数据,这种就只能先放放了。虽然我们得到了更细化的执行耗时,但其实这个命令不会告诉我们某个子工程为什么耗时。比如想要知道为什么"copying to tmp table"拷贝数据到临时表花了那么多时间,需要更进一步对这个子过程进行评估。

SHOW STATUS命令

SHOW STATUS返回各种计数,这些值有全局的(整个MySQL服务器),也有Session的(本次连接)。而如果用SHOW GLOBAL STATUS返回的计数都是全局的。SHOW STATUS返回的计数中哪些是全局的,哪些是本Session的,需要参考MySQL手册。

SHOW STATUS不是真的评估工具,它仅仅返回MySQL的各种活动的计数。这些计数中只有一个Innodb_row_lock_time表示的时间,并且计数是全局的,所以也没啥用。

所以我们要结合一个SQL语句执行的前后计数来猜测哪些动作比较耗费时间。最重要的计数是handler counters 和 temporary file and table counters。让我们先把计数清零,看看这个例子:

> FLUSH STATUS;

> SELECT * FROM sakila.nicer_but_slower_film_list;

> SHOW STATUS WHERE Variable_name LIKE 'Handler%'

OR Variable_name LIKE 'Created%';

clip_image007

clip_image008

大概可以看出,这个SQL执行过程中,用了3次临时表——其中两个表在磁盘上,做了很多没有索引加速的都操作(Handler_read_rnd_next)。从这个结果猜测,可能这个select查询了一个view,此view需要执行一个未加索引的join。

要注意SHOW STATUS操作本身自己就会出发一些计数增加,比如说写两次表格,所以前面一条SQL语句对应的临时表的操作计数应该在结果上减去2。

这得注意的是,SHOW STATUS得到的信息可能和EXPLAIN差不多,但EXPLAIN只是预测,并不是真是执行的结果。EXPLAIN不会告诉你临时表是在内存还是在磁盘这种重要信息。

耗时SQL语句日志

MySQL可以在日志中记录耗时的SQL操作,Percona Server(MySQL fork出来的另外开源实现)记录的更细。以SHOW PROFILE章节中的SQL语句为例,Log是这样的:

clip_image009从中可以看出,这条语句执行过程中创建了3个临时表,其中两个表在磁盘上。

相比于SHOW STATUS和SHOW PROFILE,耗时SQL语句日志记录更详细的信息,特别是配合pt-query-digest日志分析工具,你可以从日志中方便找到对应的SQL语句的位置。Pt-query-digist可以为SQL语句输出统计头:

# Query 1: 0 QPS, 0x concurrency, ID 0xEE758C5E0D7EADEE at byte 3214 _____

然后用shell命令就能从日志文件中拉出对应的日志:

tail -c +3214 /path/to/query.log | head -n100

全局性能统计(Performance Schema)

全局性能统计在MySQL5.5中开始引入,虽然5.5版本中不支持SQL语句级别的统计,但还是能提供一些有用的信息,比如:

> SELECT event_name, count_star, sum_timer_wait

-> FROM events_waits_summary_global_by_event_name

-> ORDER BY sum_timer_wait DESC LIMIT 5;

得到:

clip_image011

5.6以后的版本,应该会更有用。

posted @ 2015-06-04 15:00 jan4984 阅读(1297) 评论(0) 推荐(0)
摘要: frisby是一个nodejs的rest api测试框架。一般来讲,因为nodejs是众所周知的异步编程模式,api以.after()方法一步步走:frisby.create('login') .get('http://httpbin.org/login',{usernmae:xxx,passwo... 阅读全文
posted @ 2015-05-13 16:07 jan4984 阅读(478) 评论(0) 推荐(1)
摘要: 整体集成架构在企业应用中很常见。这种架构下的小应用,不论是开发、测试还是部署,都能较好完成。但是对于复杂的大型程序,整体集成架构则成为了开发和部署的绊脚石。继续发布基本已经不可能了,开发也被牢牢限制在之前选择的技术框架中。因此对于大型应用,采用微服务架构将其分解为一组服务值得一试。 微服务架构优点多多。一个微服务的源代码很容易被理解,开发部署也不需要对其他模块有什么依赖。另外在一个微服务中应用新技术框架更简单容易。 微服务架构缺点也不是没有。东西一分解以后,一个应用会变成很多零碎,你或许需要一个像PaaS那样高度自动化的平台来管理这些零碎。在开发阶段,你还要考虑如何处理数据碎片化。总的来说,对于需要快速迭代的大型程序,特别是SaaS风格的应用来讲,值得一试。 阅读全文
posted @ 2014-10-10 18:26 jan4984 阅读(1147) 评论(0) 推荐(0)
摘要: TASKapt_task_create(void *obj, apt_task_msg_pool_t *msg_pool, apr_pool_t *pool)apt_task_destroy(apt_task_t *task)销毁任务及所有子任务apt_task_add(apt_task_t *task, apt_task_t *child_task)加入一个子任务apt_task_start(apt_task_t *task)如果vtable.start存在,则运行之,否则以apt_task_run()为线程入口创建并启动新的线程。apt_task_run()按照vtable.on_pre_ 阅读全文
posted @ 2014-03-18 10:46 jan4984 阅读(1110) 评论(0) 推荐(1)
只有注册用户登录后才能阅读该文。 阅读全文
posted @ 2014-02-10 17:56 jan4984 阅读(81) 评论(1) 推荐(1)
摘要: //based on Android2.3 QCom MSM7227A AR6003-v806 source.learning by wifi sta enablingLoad driver:com.android.server.WifiService.setWifiEnabled(true)android.net.wifi.WifiStateTracker.loadDriver()hardware/libhardware_legacy/wifi/wifi.c: wifi_load_driver()start init service "init.svc.wlan_tool" 阅读全文
posted @ 2013-09-18 19:41 jan4984 阅读(343) 评论(0) 推荐(0)
点击右上角即可分享
微信分享提示