生产环境高并发MySQL SQL语句优化案例

时间:2021-01-01 17:58:45

生产环境高并发MySQL SQL语句优化10条案例

声明:本案例为老男孩linux运维实战培训的数据库优化教学案例,如有转载务必保留本版权声明

在实际工作中,运维或DBA人员经常会根据数据库的慢查询日志来抓出执行慢的SQL语句,然后,或自行处理或扔给开发处理,好点的DBA可能会和开发商量共同解决慢查询的问题,如果是调参、索引问题,那就简单了,有的时候调参索引优化没余地了,还有根据语句的功能拆分或者改成程序解决,当然也可能会调整DB架构。下面的案例主要是告诉大家,数据库的优化不都是运维,DBA的事,这一点老男孩培训的学生也是有欠缺的,工作中遇到问题束手束脚,又不好意思问开发,总是自己扛,解决憋的头大的不行,还要半夜里苦苦找老男孩老师帮忙,其实,开发、架构、产品等所有部分都有义务配合,只有通力配合,运维及DBA才能完成数据库优化的工作,其他的职位也是如此的,因此,请不要把自己孤立在孤军奋战的情况,团队的力量才是最大的。

慢查询问题是几乎数据库性能的最直接的原因了,每个运维和DBA都必须要面对,例如首先要开启慢查询及没有走索引的日志,然后写程序分析归类有问题的日志,最后发到相关人的信箱里,紧急的可以短信提醒,这是我们工作中的做法,当然还包括分析binlog,及数据库的状态日志,掌握数据库的性能指标趋势。

下面分析归类后的慢查询日志,以及解决慢查询日志最终方法,这些都是实实在在的生产案例总结,与老男孩的博友们分享。

Slow log很多时候是由order by引起的,当explain语句有Using where; Using temporary; Using filesort的信息,有这个情况就会效率低了。解决这个的关键要在order by的字段上做索引。

请看下面的例子:

案例1:分析归类后的慢查询日志如下。

Report for slow logs: /data/3306/slow-log.log.1

6.26k queries total, 135 unique

Sorted by 't_sum'

Grand Totals: Time 34.11k s, Lock 0 s, Rows sent 57.67k, Rows Examined 3.84M

______________________________________________________________________ 001 ___

Count: 2.17k(34.64%)

Time: 11031 s total, 5.090448 s avg, 3 s to 18 s max(32.34%)

95% of Time : 9605 s total, 4.667153 s avg, 3 s to 11 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 10 avg, 0 to 10 max(36.35%)

Rows examined : 20 avg, 0 to 37 max(1.11%)

Database: docresource

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (2167) of query, 100.00% (6256) of all users

Query abstract:

SELECT t.cor_id,t.boy_title_upper,t.cor_boy_title,t.cor_boy_order,t.cor_boy_description,t.cor_boy_state FROM t_cordoc t WHERE t.cor_boy_state=N AND t.boy_title_upper='S' ORDER BY t.cor_boy_order ASC LIMIT N;

Query sample:

SELECT T.COR_ID,T.BOY_TITLE_UPPER,T.COR_BOY_TITLE,T.COR_BOY_ORDER,T.COR_BOY_DESCRIPTION,T.COR_BOY_STATE FROM t_cordoc T where T.COR_BOY_STATE=1 and T.BOY_TITLE_UPPER='��褰╃�? ORDER BY T.COR_BOY_ORDER ASC LIMIT 10;

最终解决方案:用java程序在内存排序。

老男孩点评:数据库优化不一定就要改参数,建索引,不适合数据库干的事完全可以拿出来交给程序干,或者说能用程序干的就不要交给数据库(还记得老男孩对数据库的比喻了么,http://oldboy.blog.51cto.com/2561410/736710)。

案例2:分析归类后的慢查询日志如下。

______________________________________________________________________ 002 ___

Count: 911(14.56%)

Time: 5342 s total, 5.863886 s avg, 3 s to 63 s max(15.66%)

95% of Time : 4381 s total, 5.06474 s avg, 3 s to 14 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 9 avg, 1 to 10 max(14.53%)

Rows examined : 759 avg, 20 to 13.61k max(17.99%)

Database: docresource

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (911) of query, 100.00% (6256) of all users

Query abstract:

SELECT boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit FROM t_doc WHERE boy_state IN (N4) AND boy_creator_user_id_encrypt='S' ORDER BY boy_latest_edition_time DESC LIMIT N,N;

Query sample:

select boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit from t_docwhere boy_state in (1,2,3,4) and boy_creator_user_id_encrypt='tAQREAwRXWkJBUAoL' order by BOY_LATEST_EDITION_TIME DESC limit 0,10;

最终解决方案:添加适合的索引

alter table t_doc add index idx_create_user_iden_edittime(boy_creator_user_id_encrypt, boy_latest_edition_time);

案例3:分析归类后的慢查询日志如下。

______________________________________________________________________ 003 ___

Count: 1.00k(16.06%)

Time: 5114 s total, 5.088557 s avg, 3 s to 17 s max(14.99%)

95% of Time : 4426 s total, 4.639413 s avg, 3 s to 10 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 10 avg, 8 to 10 max(17.28%)

Rows examined : 10 avg, 8 to 10 max(0.26%)

Database: docresource

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (1005) of query, 100.00% (6256) of all users

Query abstract:

SELECT boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit FROM t_doc WHERE boy_title_upper IN (S10);

Query sample:

select boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit from t_docwhere boy_title_upper in ('���������濂崇��?,'灏����?,'���╁コ骞介��2?,'��绾垫����娴枫�?,'榛����?,'棣�娓��靛奖����濂?,'��涓���瑗挎���?,'����璐?,'绉�娌�','寰���');

最终解决方案:有用到boy_title_upper的索引,慢的原因再观察

案例4:分析归类后的慢查询日志如下。

______________________________________________________________________ 004 ___

Count: 378(6.04%)

Time: 2604 s total, 6.888889 s avg, 3 s to 65 s max(7.63%)

95% of Time : 2031 s total, 5.657382 s avg, 3 s to 17 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 5 avg, 0 to 10 max(3.24%)

Rows examined : 2.81k avg, 92 to 24.91k max(27.61%)

Database: docresource

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (378) of query, 100.00% (6256) of all users

Query abstract:

SELECT h.boy_id ,MAX(h.boy_his_edit_time) AS boy_his_edit_time FROM t_boy_his h WHERE h.boy_his_isteammate=N AND h.boy_his_state=N AND h.boy_his_editor_user_id_encrypt='S' GROUP BY h.boy_id ORDER BY h.boy_his_edit_time DESC LIMIT N,N;

Query sample:

selecth.boy_id ,max(h.boy_his_edit_time) from t_boy_his hwhere h.boy_his_editor_user_id_encrypt='pGVpWQVlYdglTaQ0Z' and h.boy_his_isteammate=1 and h.boy_his_state=1 group by h.boy_id order by h.boy_his_edit_time desc limit 0,4; 

最终解决方案:

alter table t_boy_his add index editor_user_iden_docid(boy_his_editor_user_id_encrypt, boy_id);

1,sql改成:SELECT h.boy_id ,MAX(h.boy_his_edit_time) AS boy_his_edit_time FROM t_boy_his h WHERE h.boy_his_isteammate='pGVpWQVlYdglTaQ0Z' AND h.boy_his_state=1 AND h.boy_his_editor_user_id_encrypt='S' GROUP BY h.boy_id ORDER BY null

2,再在程序里,用javaboy_his_edit_time排序。

案例5:分析归类后的慢查询日志如下。

______________________________________________________________________ 005 ___

Count: 211(3.37%)

Time: 1218 s total, 5.772512 s avg, 3 s to 30 s max(3.57%)

95% of Time : 1022 s total, 5.11 s avg, 3 s to 13 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 2 avg, 0 to 2 max(0.72%)

Rows examined : 3.61k avg, 110 to 19.59k max(19.81%)

Database: 

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (211) of query, 100.00% (6256) of all users

Query abstract:

SELECT h.boy_id ,MAX(h.boy_his_edit_time) AS boy_his_edit_time FROM t_boy_his h WHERE h.boy_his_isteammate=N AND h.boy_his_state=N AND h.boy_his_editor_user_id=N GROUP BY h.boy_id ORDER BY h.boy_his_edit_time DESC LIMIT N,N;

Query sample:

selecth.boy_id ,max(h.boy_his_edit_time) as boy_his_edit_time from t_boy_his hwhere h.boy_his_isteammate=1 and h.boy_his_state=1 and h.boy_his_editor_user_id=300000178518 group by h.boy_id order by h.boy_his_edit_time desc limit 0,2;

最终解决方案:此sql由查前面一个sql代替,删除。

案例6:分析归类后的慢查询日志如下。

______________________________________________________________________ 006 ___

Count: 30(0.48%)

Time: 940 s total, 31.333333 s avg, 3 s to 77 s max(2.76%)

95% of Time : 790 s total, 28.214286 s avg, 3 s to 69 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 1 avg, 1 to 1 max(0.05%)

Rows examined : 10.96k avg, 1.82k to 28.12k max(8.56%)

Database: docresource

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (30) of query, 100.00% (6256) of all users

Query abstract:

SELECT COUNT(*) FROM t_boy_his WHERE boy_his_check_expert_id_en = 'S' AND boy_his_check_state=N AND boy_his_deal_time BETWEEN 'S' AND 'S';

Query sample:

SELECT COUNT(*)FROM T_BOY_HISWHEREBOY_HIS_CHECK_EXPERT_ID_EN = 'uAwgHUUNYU1lfUFkJ' AND BOY_HIS_CHECK_STATE=1 AND BOY_HIS_DEAL_TIME BETWEEN '2009-02-16 00:00:00' AND '2009-02-24 00:00:00';

最终解决方案:此sql有用到BOY_HIS_CHECK_EXPERT_ID_EN的索引,再观察

案例7:分析归类后的慢查询日志如下。

______________________________________________________________________ 007 ___

Count: 134(2.14%)

Time: 823 s total, 6.141791 s avg, 3 s to 23 s max(2.41%)

95% of Time : 698 s total, 5.496063 s avg, 3 s to 15 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max (0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 10 avg, 2 to 10 max(2.31%)

Rows examined : 792 avg, 53 to 9.55k max(2.76%)

Database: 

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (134) of query, 100.00% (6256) of all users

Query abstract:

SELECT boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit FROM t_doc WHERE boy_state IN (N4) AND boy_creator_user_id_encrypt='S' ORDER BY boy_goodcount DESC LIMIT N,N;

Query sample:

select boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit from t_docwhere boy_state in (1,2,3,4) and boy_creator_user_id_encrypt='lGwdcWgJBBAtVCnER' order by BOY_GOODCOUNT desc limit 380,10;

最终解决方案:跟产品确认已经没用的功能,去掉

老男孩点评:数据库优化不一定就要该参数,建索引,有些过时的功能,还有后台内部的全表扫描等查询,可以单独加个从库,这是老男孩培训的根据内外业务选择读库的重要思路。

案例8:分析归类后的慢查询日志如下。

______________________________________________________________________ 008 ___

Count: 130(2.08%)

Time: 730 s total, 5.615385 s avg, 3 s to 21 s max(2.14%)

95% of Time : 614 s total, 4.99187 s avg, 3 s to 14 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 10 avg, 5 to 10 max(2.24%)

Rows examined : 763 avg, 32 to 4.16k max(2.58%)

Database: 

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (130) of query, 100.00% (6256) of all users

Query abstract:

SELECT boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit FROM t_doc WHERE boy_state IN (N4) AND boy_creator_user_id_encrypt='S' ORDER BY boy_goodcount ASC LIMIT N,N;

Query sample:

select boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit from t_docwhere boy_state in (1,2,3,4) and boy_creator_user_id_encrypt='bAQReRlFZX0BZW1oD' order by BOY_GOODCOUNT asc limit 370,10;

最终解决方案:跟产品确认已经没用的功能,去掉。

老男孩点评:不战而屈人之兵,这个很棒。当然,分业务,读不同的库,等等都是好的解决办法,而不是动不动就拆表拆库,大手术不是那么容易的,关键是有时有更简单的解决方案,都是一些架构会议搞的大家总是东施效颦,有时并不是唯一的方法。

案例9:分析归类后的慢查询日志如下。

______________________________________________________________________ 009 ___

Count: 83(1.33%)

Time: 527 s total, 6.349398 s avg, 3 s to 29 s max(1.54%)

95% of Time : 408 s total, 5.230769 s avg, 3 s to 16 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 1 avg, 1 to 1 max(0.14%)

Rows examined : 1.08k avg, 96 to 3.84k max(2.34%)

Database: 

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (83) of query, 100.00% (6256) of all users

Query abstract:

SELECT COUNT(DISTINCT h.boy_id) FROM t_boy_his h WHERE h.boy_his_isteammate=N AND h.boy_his_editor_user_id=N;

Query sample:

SELECT COUNT(DISTINCT H.BOY_ID) FROM T_BOY_HIS H WHERE H.BOY_HIS_ISTEAMMATE=1 AND H.BOY_HIS_EDITOR_USER_ID=300000328622;

最终解决方案:

使用editor_user_iden_docid索引

1,sql:SELECT h.boy_id FROM t_boy_his h WHERE h.boy_his_isteammate=N AND h. BOY_HIS_EDITOR_USER_ID_ENCRYPT =N group by boy_id;

2,取得前一sql返回的结果集的size().

案例10:分析归类后的慢查询日志如下。

______________________________________________________________________ 010 ___

Count: 94(1.50%)

Time: 511 s total, 5.43617 s avg, 3 s to 21 s max(1.50%)

95% of Time : 428 s total, 4.808989 s avg, 3 s to 11 s max

Lock Time (s) : 0 total, 0 avg, 0 to 0 max(0.00%)

95% of Lock : 0 total, 0 avg, 0 to 0 max

Rows sent: 10 avg, 3 to 10 max(1.60%)

Rows examined : 747 avg, 32 to 5.14k max(1.83%)

Database: 

Users: 

ett_oldboy@ 10.0.1.28 : 100.00% (94) of query, 100.00% (6256) of all users

Query abstract:

SELECT boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit FROM t_doc WHERE boy_state IN (N4) AND boy_creator_user_id_encrypt='S' ORDER BY boy_score DESC LIMIT N,N;

Query sample:

select boy_id,boy_class,boy_title,boy_creator_user_id,boy_creator_user_nick,boy_latest_edition,boy_latest_url,boy_created_time,boy_latest_edition_time,boy_inner_pic_count,boy_outer_pic_count,boy_keywords,boy_click_count,boy_his_count,boy_attendee_count,boy_summary,boy_state,boy_goodcount,boy_badcount,boy_first_img,boy_title_upper,boy_import_tag,boy_topic_count,boy_post_count,boy_creator_user_id_encrypt,boy_id_encrypt,boy_score,last_edit_user_id_en,champion_user_nick,champion_user_id_en,champion_credit from t_docwhere boy_state in (1,2,3,4) and boy_creator_user_id_encrypt='icVpAUWBxB2xOUUB1' order by BOY_SCORE desc limit 490,3;

最终解决方案:

alter table t_doc add index creator_user_iden_docscore(boy_creator_user_id_encrypt, BOY_SCORE);

索引清理:这些索引没起到作用,删除索引

alter table t_doc drop index IDX_BOY_BOY_CLASS

alter table t_doc drop index IDX_BOY_IMPORT_TAG

alter table t_boy_his drop index IDX_BOY_CLASS

老男孩点评:索引并非越多越好,曾经给个企业做技术顾问,由于有慢查询,结果管理员把表的所有字段都建立了索引,以为能解决问题,结果不但没解决问题,反而更慢了。数据库优化和战场打仗是一样的,法无定法只要能打败敌人,所有的力量和方法都是可以用的,这也说明了思路决定出路的重要性。

 

本文出自 “老男孩linux培训” 博客,转载请与作者联系!