用户反映MYSQL中某个表前端查询很慢,前端显示需要10多秒,于是我方把监控到的SQL语句执行查询,结果如下:
</>code
- SELECT
- sum(num)FROM
- `user_coin_log` force index (ix_5)WHERE
- `create_time` >= 1584892800AND `create_time` < 1584979200AND `source` = 5AND `uid` IN (
- 23,
- 24,
- 26,
- 29,
- 32,
- 33,
- 38,
- 42,
- 52,
- 59,
- 68,
- 69,
- 71,
- 72,
- 73,
- 79,
- 83,
- 85,
- 108,
- 111,
- 139,
- 229,
- 261,
- 280,
- 281,
- 283,
- 296,
- 298,
- 308,
- 401,
- 423,
- 490,
- 523,
- 650,
- 653,
- 776,
- 903,
- 913,
- 966,
- 997,
- 1030,
- 1381,
- 1704,
- 1809,
- 1922,
- 1943,
- 2011,
- 2037,
- 2146,
- 2459,
- 2757,
- 3055,
- 3087,
- 3098,
- 3280,
- 3315,
- 3427,
- 3701,
- 5132,
- 5625,
- 6646,
- 7628,
- 8040,
- 8464,
- 23304)AND `coin_id` = 1LIMIT 1
执行时间需要5.466S,于是分析这个SQL语句,从语句的结构来看,where条件有时间create_time,uid等条件过滤,直觉应该不至于如此慢,而且该表上是有一个索引ix_5,同时覆盖了create_time,uid,source,coin_id,num等列的,但此SQL执行计划并没有走这个索引,而是走了一个单列索引UID不太合理,于是经过多方面排查与尝试,如果把这个UID条件去掉,或把UID里面的列表值大量减少,这个时候会走ix_5索引,甚至如果让uid in一个临时表(把所有的uid值建成1个临时表),这个时候也会走ix_5索引,执行时间会在0.8s内!
顺着这个方向继续排查,发现网上有不少类似的案例,其现象都是:in后面如有太多值,MYSQL会认为全面扫描会更有效率,看来这一点还是不够oracle的优化器智能啊!于是尝试采用强制索引的方案来解决,具体加上(force index (ix_5))后,语句变成:
</>code
- SELECT
- sum(num)FROM
- `user_coin_log` force index (ix_5) WHERE
- `create_time` >= 1584892800AND `create_time` < 1584979200AND `source` = 5AND `uid` IN (
- 23,
- 24,
- 26,
- 29,
- 32,
- 33,
- 38,
- 42,
- 52,
- 59,
- 68,
- 69,
- 71,
- 72,
- 73,
- 79,
- 83,
- 85,
- 108,
- 111,
- 139,
- 229,
- 261,
- 280,
- 281,
- 283,
- 296,
- 298,
- 308,
- 401,
- 423,
- 490,
- 523,
- 650,
- 653,
- 776,
- 903,
- 913,
- 966,
- 997,
- 1030,
- 1381,
- 1704,
- 1809,
- 1922,
- 1943,
- 2011,
- 2037,
- 2146,
- 2459,
- 2757,
- 3055,
- 3087,
- 3098,
- 3280,
- 3315,
- 3427,
- 3701,
- 5132,
- 5625,
- 6646,
- 7628,
- 8040,
- 8464,
- 23304) AND `coin_id` = 1LIMIT 1
再次执行:
加上HINT后,SQL效率得到了10倍以上的提升,由原来的5.4S下降到0.3S,性能提升效果显著!
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛