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秒。

執行計劃如下:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章