Mysql慢sql优化案例

一 问题描述

生产有一个这样的慢sql:

SELECT DISTINCT

  m1.meetingid AS meetingid,

  m1.starttime AS START,

  m1.endtime AS END,

m1.title AS title,

j.userid AS uid,

j.type AS TYPE,

m1.cuserid AS cuserid

FROM

  MEETINGINFO m1

  INNER JOIN JOININFO j

    ON (m1.meetingid = j.meetingid)

    AND (

      m1.cuserid IN (192379)

      OR j.userid IN (192379)

    )

    AND m1.dostatus IN (2, 4)

ORDER BY m1.starttime DESC

LIMIT 0, 10

查询需要2.3秒。

MEETINGINFO有三十万条数据,JOININFO有将近98万条数据。

执行计划如下:

 

二 优化思路

看到查询条件里有m1.cuserid IN (192379),却选择了starttime这个索引来扫描m1,遂查询下该列上是否有索引:

SHOW INDEXES FROM MEETINGINFO #看到没有相关索引

再看下该列是否适合创建索引:

 

重复率不算高,还可以。

尝试在该列上创建索引:

CREATE INDEX ind_cuserid ON MEETINGINFO(cuserid);

发现执行计划依然没选择走该索引,原因有二:

① cuserid是varchar类型的,而sql里192379是数值类型,发生数据类型转换,会导致索引失效

② OR j.userid IN (192379)里的OR会导致无法走索引,需要用UNION ALL来代替OR。

三 解决办法

改写sql:

SELECT DISTINCT   aa.meetingid,aa.start,aa.end,aa.title,aa.uid,aa.type,aa.cuserid 
FROM
  (SELECT 
    m1.meetingid AS meetingid,
    m1.starttime AS START,
    m1.endtime AS  END,
  m1.title AS title,
  j.userid AS uid,
  j.type AS TYPE,
  m1.cuserid AS cuserid 
  FROM
    MEETINGINFO m1 
    INNER JOIN JOININFO j 
      ON (m1.meetingid = j.meetingid) 
      AND (m1.cuserid IN ('192379')) 
      AND m1.dostatus IN (2, 4) 
  UNION  ALL 
  (SELECT 
    m1.meetingid AS meetingid,
    m1.starttime AS START,
    m1.endtime AS 
  END,
  m1.title AS title,
  j.userid AS uid,
  j.type AS TYPE,
  m1.cuserid AS cuserid 
  FROM
    MEETINGINFO m1 
    INNER JOIN JOININFO j 
      ON (m1.meetingid = j.meetingid) 
      AND j.userid IN ('192379') 
      AND m1.dostatus IN (2, 4)
    )
  ) aa 
ORDER BY aa.start DESC LIMIT 0,10 

查询时间从2秒多降到了0.02秒。

执行计划如下:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL SQL优化是指对MySQL数据库的查询语句进行优化,以提高查询效率和性能。下面是一个MySQL SQL优化案例: 假设有一个订单表(order)和一个商品表(product),订单表有订单ID、订单时间和订单金额等字段,商品表有商品ID、商品名称、商品价格等字段。现在要查询订单表中某个时间段的订单总金额,以及该时间段内销售额最高的商品。 初始查询语句如下: ``` SELECT SUM(order_amount) AS total_amount, product_name FROM order JOIN product ON order.product_id = product.product_id WHERE order_time BETWEEN '2022-01-01 00:00:00' AND '2022-01-31 23:59:59' GROUP BY product_id ORDER BY total_amount DESC LIMIT 1; ``` 这个查询语句的问题在于,在JOIN操作时没有使用索引,导致查询效率低下。为了提升性能,可以对查询语句进行优化。 优化后的查询语句如下: ``` SELECT SUM(order_amount) AS total_amount, product_name FROM order JOIN product ON order.product_id = product.product_id WHERE order_id IN ( SELECT order_id FROM order WHERE order_time BETWEEN '2022-01-01 00:00:00' AND '2022-01-31 23:59:59' ) GROUP BY product_id ORDER BY total_amount DESC LIMIT 1; ``` 优化后的查询语句在子查询中使用了索引,将order_time的条件先筛选出符合要求的订单ID,再使用该子查询进行JOIN操作,可以提高查询效率。同时,由于只需要查询销售额最高的商品,使用LIMIT 1可以限制结果集的大小,减少数据处理的负担。 通过这个优化案例,可以看到,MySQL SQL的优化需要根据具体需求进行,合理使用索引、子查询、LIMIT等操作,以提高查询效率和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值