成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

平臺數據激增破千萬下的SQL優化

數據庫 其他數據庫
利用Explain,可以快速的分析出缺失的索引,比如檢查Join或者Order by中使用的字段,對于大表,有無索引會有幾十甚至上百倍的效率差異。但索引也并非越多越好,過多的索引會對插入及更新造成比較大的影響。

背景

公司一直維護著學生體測平臺,最近中標一個項目,從原本零零散散的錄入體測數據,驟增到幾天內上百萬的用戶及上千萬的體測數據涌入系統,結果各種異常、慢查、連接拒絕,層出不窮...

過多的慢sql會導致數據庫CPU飄升、連接無法及時釋放、連接池超出限制,原本幾毫秒的查詢也遲遲無法得到響應,拖垮整個系統,而且系統中使用了消息隊列,還導致了消息堆積,重啟服務后,服務瞬間又被打滿,內存飄升、頻繁的full GC...之前也整理過不少sql優化的文章,但沒多少用戶時,很少去關注,用戶驟增時,還是經歷了一番“洗禮”,這里記錄一下這幾天的優化點。

索引使用

索引優化,是一個老生常談的問題了。項目中,利用云平臺或者配合druid搭建慢sql報警機制,可以篩選出執行過慢的語句,然后,再借助explain去分析(有關explain的用法之前做過詳細講解:sql調優之explain關鍵字詳解)。

利用explain,可以快速的分析出缺失的索引,比如檢查join或者order by中使用的字段,對于大表,有無索引會有幾十甚至上百倍的效率差異。但索引也并非越多越好,過多的索引會對插入及更新造成比較大的影響。

explain之后,type為ALL的,即未使用到索引,多數還是比較容易處理的。這里順帶列舉一些常見的索引失效場景:

未遵循最左前綴匹配導致索引失效

使用函數導致索引失效

select * from student where name = left('云端行筆666',4)。

計算導致索引失效

select * from student where id + 1 = 666。

類型轉換導致索引失效

select * from student where convert(id,char) = '666'。

不等于(!= 或者<>)索引失效

select * from student where name != "云端行筆"。

like模糊匹配以通配符開頭導致索引失效

select * from student where name like "%云端行筆"。

索引字段使用is not null導致失效

select * from student where name is not null。

OR前后存在非索引的列,索引失效

select * from student where id =1 or name = '云端'。

這里列舉兩個此次優化的示例:

示例一:find_in_set

業務中有這樣一個場景,上級需要看到其所有下級的數據,如省及單位需要能查看其下所有市區縣的學校。為了方便,之前將學生所隸屬的學校以及其上級省市區單位,記錄在一個字段sponsor_ids中,然后通過find_in_set查詢,如下:

SELECT grade FROM enroll 
WHERE match_id = 60 AND FIND_IN_SET(36, sponsor_ids) 
GROUP BY grade ORDER BY grade

這樣設計,代碼寫起來很方便,但數據量級大是,查詢效率極其低下,因為find_in_set無法使用索引。

優化:事先查詢所屬下級,然后通過in查詢使用索引

SELECT
	s.id
FROM
( SELECT * FROM sponsor WHERE `status` = 1 AND  superior_id IS NOT NULL order by level asc ) s,
  ( SELECT @pid := #{sponsorId} ) pd
WHERE
FIND_IN_SET( superior_id, @pid ) != 0
AND @pid := concat( @pid, ',', id )
SELECT grade FROM enroll 
WHERE match_id = 60 AND  sponsor_id in (36) 
GROUP BY grade ORDER BY grade

雖然在查詢下級機構時,也使用了find_in_set,但機構表數據量有限,全表掃也無太大壓力,而enroll報名表使用in查詢后,效率明顯提升,由幾秒提升到幾十毫秒。

示例二:聯合索引

還有一些其他情況,比如:

SELECT sponsor_id, count(sponsor_id) AS sponsor_count FROM enroll 
WHERE match_id = 60 
GROUP BY sponsor_id

這句sql,是用于統計某次體測活動中,各個學校的報名人數。設計表時在match_id,sponsor_id上,分別建立的索引,報名人數不多時,效率還可以。但報名人數幾十萬之后,發現查詢效率明顯下降,需要幾秒鐘。explain分析如下:

從上述的分析可以看出,查詢使用了索引,但只用到了match_id這一個索引,而extra中顯示了using temporary,即使用了中間表進行分組,并未用到索引,數據量達到一定量級后,中間表也會很大,效率自然也就降低了。

為此,針對該查詢,建立了match_id和sponsor_id的聯合索引,explain發現,不在使用中間表,實際查詢效率也明顯提升,大概幾百毫秒。(使用到覆蓋索引,不需要回表查詢)

批量插入與更新(避免循環單條插入)

批量操作,是業務中很常見的,比如批量導入學生,簡單粗暴的一種做法就是,for循環,然后在循環中insert,如:

for (int i = 0; i < 50000; i++){
  Student student = new Student("云端行筆" + i,24,"北京市" + i,i + "號");
  studentMapper.insert(student);
}
<insert id="add" parameterType="com.peng.Student">
  INSERT INTO TEST(ID,Student) VALUES(#{id},#{student});
</insert>

當插入百八十條數據時,不會覺得效有多低,但當插入上萬條數據時,循環插入可能需要一兩分鐘甚至更久,這就無法忍受了。正確的打開方式:

<insert id="batchAdd" parameterType="java.util.List">
  INSERT INTO TEST(ID,Student)
VALUES
  <foreach collection="list" item="item" index="index" separator="," >
    (#{item.id},#{item.student})
    </foreach>
</insert>

避免全表

業務中有這樣一個需求,導入學生時,需要對比學生編號是否有重復。之前的實現方式是將student表中的所有數據,全都查出來,加載到內存,在內存中與導入的數據逐條對比。上百萬的數據,而且還是select *,結果可想而知...

這種掃全表、select *的做法,回頭來看,其實是很初級的,但實際開發中,很多時候,為了圖省事兒,可能就隨手把坑埋下去了...

無能為力的SQL

業務中有這樣一個場景:學生參與體測活動,需要報名,因此,除了student學生表之外,還有一張enroll報名表,用于記錄學生在多個體測活動中的報名狀態。業務中需要統計所有未報名的學校,思路很簡單,就是學生表和報名表取差集,然后統計差集中有哪些學校,SQL如下:

select distinct(s.sponsor_id) from student s
LEFT JOIN enroll e on e.student_id = s.id
where s.status = 1 and e.id is null

問題在于,一個地區會有幾百萬甚至上千萬的學生,如此龐大的兩張表取交集,太慢了.,優化好久也沒思路...(歡迎評論區指點迷津)。SQL無力了,最終選擇,將未報名的學校數據提前統計計算,放在緩存之中,有學生狀態或者報名狀態發生變更,則去更新。該思路也是類似于數據平臺,千萬級別的數據,實時統計,肯定會有效率問題,因此,往往會在數據服務中非實時計算。

總結

以上是平臺數據爆發期間,優化項目是的一些感悟,隨筆一記。

責任編輯:姜華 來源: 今日頭條
相關推薦

2022-10-14 17:24:35

MySQLSQL優化

2022-07-05 21:31:21

索引SQL分庫分表

2017-02-05 17:27:43

2010-03-23 11:55:32

云計算

2023-11-30 15:10:20

物聯網數據物聯網平臺

2012-09-24 10:20:24

草根應用平臺數據

2018-03-30 14:30:10

數據庫SQL語句性能優化

2018-07-30 14:40:01

MySQLSQL查詢

2019-05-31 12:03:06

SQLHadoop大數據

2022-07-04 23:24:28

sql優化監控

2012-12-26 09:23:56

數據庫優化

2014-04-09 14:15:23

2024-03-11 07:38:15

歐拉數據血緣數據應用數據治理

2023-02-24 16:37:04

MySQL數據查詢數據庫

2018-07-11 20:07:06

數據庫MySQL索引優化

2015-07-14 17:12:49

2009-12-02 10:33:34

LINQ to SQL

2023-07-26 08:21:33

2016-12-09 09:31:22

HadoopSQL大數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文亚洲视频 | 国产精品久久久久久久岛一牛影视 | a级片网站| 黄 色 毛片免费 | 91美女在线观看 | 影音先锋中文字幕在线观看 | 久热免费 | 国产精品久久久久久久久久久久久 | 久久久久久国产 | 亚洲h在线观看 | 午夜99| 日韩国产一区二区三区 | 国产中文| 国产精品久久久 | 久久er精品 | 中文字幕高清免费日韩视频在线 | 久久香焦 | 亚洲国产精品激情在线观看 | 亚洲精品高清视频在线观看 | 日韩欧美三区 | 中文字幕福利视频 | 99久久精品一区二区成人 | 国产在线精品一区二区三区 | 精品一区二区三区中文字幕 | 国产精品久久久久久妇女6080 | 欧美午夜剧场 | 欧美一级片久久 | 日韩精品久久久 | 色综合99| 精品国产乱码久久久久久久久 | 国产在线观看一区二区 | 一区二区在线不卡 | 在线观看国产视频 | 国内精品一区二区三区 | 亚洲视频中文字幕 | 国产成在线观看免费视频 | 日韩中文在线 | 成人h免费观看视频 | 亚洲精品一区中文字幕乱码 | 国产99久久精品一区二区永久免费 | 日韩在线视频一区 |