前言:本案例是前段时间某投票活动的优化,在阿里云监控上发现RDS CPU使用率竟然超过60%,按照常规套路,首先第一个想到的就是没有使用合适的索引。

    说时迟,那时快,通过show processlist捕捉到大量的线程同时在执行相同的sql,我们来看下

    1. CREATE TABLE `xxx` (
    2. `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    3. `group_id` int(11) unsigned DEFAULT '0' COMMENT '分组id',
    4. `vote_id` int(11) unsigned NOT NULL COMMENT '投票id',
    5. `id_num` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '编号',
    6. `title` varchar(25) CHARACTER SET utf8mb4 NOT NULL COMMENT '标题',
    7. `group_img` varchar(100) DEFAULT NULL COMMENT '分组图片',
    8. `list_img` varchar(100) DEFAULT NULL COMMENT '列表图片',
    9. `first_banner` varchar(100) DEFAULT NULL COMMENT '第一张banner图',
    10. `real_num` int(11) unsigned DEFAULT '0' COMMENT '真实的票数(点赞数)',
    11. `add_num` int(11) DEFAULT '0' COMMENT '运营人员增减的票数(点赞数),允许为负,前后台显示real和add之和',
    12. `real_cai_num` int(11) unsigned DEFAULT '0' COMMENT '真实点踩数',
    13. `add_cai_num` int(11) DEFAULT '0' COMMENT '运营人员增减的点踩数,允许为负,前后台显示real和add之和',
    14. `_create` int(11) unsigned NOT NULL COMMENT '创建时间',
    15. `_update` int(11) unsigned DEFAULT NULL COMMENT '修改时间',
    16. `create_user` varchar(32) NOT NULL COMMENT '创建人,有可能是用户的openid',
    17. `update_user` int(11) unsigned DEFAULT NULL COMMENT '修改人',
    18. PRIMARY KEY (`id`),
    19. KEY `index_group` (`group_id`) USING BTREE,
    20. KEY `index_vote_id` (`vote_id`,`status`) USING BTREE
    21. ) ENGINE=InnoDB AUTO_INCREMENT=2084 DEFAULT CHARSET=utf8 COMMEN
    22. SELECT `vote_id`,`is_local`,`id_num`,`id`,`title`,`declare`,`remark`,`video`,`link_video`,`video_pic`, (real_num+add_num) as vote_num, (real_cai_num+add_cai_num) as cai_num FROM `vote_candidate` WHERE (`status`=1) AND (`vote_id`='172') AND (`id_num`='38') LIMIT 1

    为了安全,去掉了部分字段跟注释,咋一看,就知道这个又是投票相关的SQL,当时心里妈卖批,开发狗又不用redis来做计数器,但是又没办法,项目都上线了,只能看着优化优化了,分析了一下,这个sql其实不难,添加一个索引即可以达到优化的效果。

    1. 总记录数:1830
    2. 区分度:
    3. status3
    4. vote_id59
    5. id_num237
    6. create index idx_idn_voteid_status on vote_candidate(id_num,vote_id,status);

    根据索引最左匹配原则,创建多列索引如上,再来看执行计划:

    1. {
    2. "query_block": {
    3. "select_id": 1,
    4. "table": {
    5. "table_name": "vote_candidate",
    6. "access_type": "ref",
    7. "possible_keys": [
    8. "index_vote_id",
    9. "idx_idn_voteid_status"
    10. ],
    11. "key": "idx_idn_voteid_status",
    12. "used_key_parts": [
    13. "id_num",
    14. "vote_id",
    15. "status"
    16. ],
    17. "key_length": "8",
    18. "ref": [
    19. "const",
    20. "const",
    21. "const"
    22. ],
    23. "rows": 1,
    24. "filtered": 100
    25. }
    26. }
    27. }

    看到条件都已匹配到,CPU使用率马上就降到5%以下了,看来效果还是不错的。