MySQL 5.7 优化不能只看执行计划

 就这么一条SQL要40s,看执行计划,发现rows很小,神奇了。
SELECT T1.* FROM
(SELECT 
  T.*,
  R.LOCATION_DEPART_ID AS locationDepartId,
  CASE
    WHEN T.INVENTORY_TYPE = 1 
    THEN f_fm_getFullLocationName(R.LOCATION_DEPART_ID, '50000050')
    WHEN T.INVENTORY_TYPE = 2 
    THEN 
    (SELECT f_gg_org_getorgnamepath(OT.ORG_ID,'50000050',ot.org_name)
       FROM gg_ORGANIZATION OT 
      WHERE OT.ORG_ID = R.LOCATION_DEPART_ID) 
    ELSE '' 
  END AS locationOrOrgName,
  CASE
    WHEN T.INVENTORY_TYPE = 1 
    THEN f_fm_getFullClassifyName (R.CLASSIFY_ID) 
    ELSE '' 
  END AS classifyName, 
  (SELECT 
    COUNT(
      CASE
        WHEN ii.INVENTORY_RESULT = 1 THEN 1 
      END
    ) 
  FROM
    FM_INVENTORY I,
    FM_INVENTORY_ITEM II 
  WHERE I.ID = II.INVENTORY_ID 
    AND I.TASK_ID = T.ID) AS waitInventoryNum
FROM
  FM_INVENTORY_TASK T,
  FM_INVENTORY_TASK_RANGE R 
WHERE T.ID = R.TASK_ID) T1
WHERE 1 = 1
  AND T1.FLOW_STATE = 2;
  
id  select_type         table       type   key                   key_len  ref                   rows  Extra        
--  ------------------  ----------  ------ --------------------  -------  ------------------- ------ -----------
 1  PRIMARY             <derived2>  ref    <auto_key0>           2        const                   8   (NULL)       
 2  DERIVED             T           ALL    (NULL)                (NULL)   (NULL)                  80  (NULL)       
 2  DERIVED             R           ref    IDX_RANGE_TASK_ID     111      T.ID                    1   (NULL)       
 4  DEPENDENT SUBQUERY  I           ref    IDX_INV_TASK_ID       110      T.ID                    1   Using index  
 4  DEPENDENT SUBQUERY  II          ref    IDX_INV_INVENTORY_ID  110      I.ID                    6   (NULL)       
 3  DEPENDENT SUBQUERY  OT          eq_ref PRIMARY               98       R.LOCATION_DEPART_ID    1   Using where  

 
 第一个感觉是数据库缓存的问题,检查了一下,很多配置都是默认的,于是加了一下。
[mysqld]下面添加
innodb_read_io_threads = 16
innodb_write_io_threads = 16
max_heap_table_size = 159M
tmp_table_size = 159M
sort_buffer_size = 8M
join_buffer_size = 8M
read_buffer_size = 4M
read_rnd_buffer_size = 16M
bulk_insert_buffer_size = 64M
innodb_buffer_pool_instances = 8
innodb_file_per_table = 1
innodb_thread_concurrency = 0
innodb_log_buffer_size = 6M
innodb_log_file_size = 256M 
重启数据库之后,发现性能有所提升,还是30s。只能用最传统的办法,把子查询一个个去掉,执行,发现第三个子查询去掉之后秒出。
  (SELECT 
    COUNT(
      CASE
        WHEN ii.INVENTORY_RESULT = 1 THEN 1 
      END
    ) 
  FROM
    FM_INVENTORY I,
    FM_INVENTORY_ITEM II 
  WHERE I.ID = II.INVENTORY_ID 
    AND I.TASK_ID = T.ID) AS waitInventoryNum
 用show profiles诊断发现时间耗在send data上面。
 
    检查了一下FM_INVENTORY_ITEM是明细的数据,接近800万的数据,且大部分数据集中在一个单上。找了下业务,发现是异常问题,把垃圾数据迁移出去,然后执行SQL,秒出。
    总结:MySQL里面的执行计划比较弱,有时候不能完全依赖,还是得查每张表实际的大小。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值