Mysql 的FIND_IN_SET函数慢的忧化

一个页面的查询,数据量不算太多,也不算太少,竟然用了10多秒

一、需求

    查找出卡片表里所包含的DIY卡片ID所对应的名字

 

二、sql 语句祥细信息

  SELECT cardName

     FROM diyCard

     WHERE FIND_IN_SET(id, ( SELECT group_concat(id) FROM card))

  diyCard表的数据量几千,card表的数据量几万

  原本SQL并没有这么少,这是分析后为了让大家能够更加明白的简易代码。

 

三、问题分析


  1)首先看一看索引加了没,没加,之后加了索引快了一些,但还是慢
  2)再观察代码
  最终把问题放在了FIND_IN_SET(id,(select group_concat(id) from card))
  仔细观察这段代码

  FIND_IN_SET是一个函数,里面的参数嵌套了一个子查询,意思就是说每次查找card表是否有diycard的id都可能是又运行了一次(select group_concat(id) from card),所以导致慢的根本原因。

  怎么办呢,想一想sql的执行顺序:
  1).首先执行 FROM 子句,从diycard表组装数据源(没问题)
  2).执行where子句,执行函数FIND_IN_SET,参数的数据源是(select group_concat(id) from card),就像上面说的每次查找diycard的id循环遍历都会运行(select group_concat(id) from card),在这里会消耗很多时间
  那么就从这里改造,把(select group_concat(id) from card)改成一个死数据一样,不让它每次去查数据库。
  注意把(select group_concat(id) from card)加到from后面,执行sql时直接组装数据源。还有这里的group_concat(id)让这个数据源只有一条记录,所以不会产生笛卡尔集。


四、解决问题
  

SELECT cardname
   FROM diycard, ( SELECT group_concat(id) id FROM card) temp
   WHERE
  FIND_IN_SET(id, temp.card)


忧化sql的方法有很多
  1).索引的添加
  2).对于长sql,先删除部分不引响不慢的sql,再从剩余的sqll慢慢定位出效率低的sql
  3).多使用explain(可以帮助我们分析 select 语句,让我们知道查询效率低下的原因,从而改进我们查询,让查询优化器能够更好的工作。)  

  。。。。。

文章作者介绍:

 

来自于小豹科技的田时伟-公司专注于软件基础研发平台,目前公司正在研发一款基于Netty的插件式的API网关-小豹API网关。 希望与对OpenAPI、微服务、API网关、Service Mesh等感兴趣的朋友多交流。 有兴趣的朋友请加QQ群244054462。

转载于:https://www.cnblogs.com/Tinsv/p/8316833.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值