一次SQL查詢優化實錄

一、背景

今年五月上上線了一個Web系統,面向公衆開放使用,隨着系統用戶量增長,系統性能下降的問題十分明顯,因此着手進行瓶頸點排查。

二、Tomcat優化

按照日常方法優化Tomcat7,啓用線程池、GZIP等機制(詳情請Google之),系統性能略有改善。考慮通常磁盤IO通常纔是系統關鍵瓶頸點,因此着手優化數據庫。

三、數據庫優化

當前系統使用MySQL5.1數據庫,當前的數據庫中5個關鍵表中數據平均各約10萬左右,2個基本數據表,3個關聯關係表。

安裝30天免費試用版的MONYog5.5監測數據庫狀態和SQL,將執行次數較多查詢1秒以上的語句導出,逐個分析。

 

1.增加字段索引

找出查詢條件和關聯時常用的字段,爲其增加索引後,有80%以上的語句性能得到巨大提升,查詢效率達到50毫秒以下。

需要注意的一點是,關係表中通常使用兩個字段構建主鍵,應當分別爲每個字段創建單獨的索引。

2.優化複雜關聯語句

MySQL5.x早期版本的子查詢的性能非常差,特別是嵌套子查詢,因此在程序中對查詢語句進行拆分,分爲兩到三次查詢,然後使用程序進行結果集合並。

例如,本系統中的一個需求:在某頁面要求顯示選中機構下的下級機構名稱列表,每個機構名稱後同時需要顯示其下級機構和人員的數量。由於系統中對用戶進行了人員查看分級控制,因此每個用戶進行時看到的數據並不致,不適合採用數據維護時計算的方式(就是在添加、修改、刪除機構或人員時,在相應的字段上更新累計數量)。

版本1的語句爲:

SELECT g.group_id,group_name
,((SELECT COUNT(*) FROM tbl_contacts_group AS tcg,tbl_contacts AS c WHERE tcg.group_id=g.group_id AND c.cont_id=tcg.cont_id AND is_display=1 AND cont_level>='A')
+(SELECT COUNT(*) FROM tbl_group_relation WHERE parent_id=g.group_id)) AS group_childs_num 
FROM tbl_group AS g ,tbl_group_relation AS r
WHERE g.group_id=r.group_id AND g.ec_id='5515118546' AND r.parent_id='42b8df1e-415f-45ed-bedc-6147df42bc85' ORDER BY row_id ;

 用時約5-10秒,當有高併發出現時可能更高

版本2調整爲兩條語句

SELECT g.group_id,group_name
,(SELECT COUNT(*) FROM tbl_group_relation WHERE parent_id=g.group_id) AS group_childs_num FROM tbl_group_relation AS r,tbl_group AS g 
WHERE g.group_id=r.group_id  AND r.parent_id='42b8df1e-415f-45ed-bedc-6147df42bc85' ORDER BY row_id;


SELECT tcg.group_id,COUNT(0) 
FROM tbl_contacts_group AS tcg
JOIN tbl_contacts AS c
WHERE is_display=1 AND c.cont_id=tcg.cont_id AND tcg.group_id IN (SELECT group_id FROM tbl_group_relation AS tgr WHERE tgr.parent_id='42b8df1e-415f-45ed-bedc-6147df42bc85') AND  cont_level>='A'
GROUP BY tcg.group_id  

 第1條語句約20ms,第二條約500ms,使用程序合併的時間可以忽略

 

版本3中將第二條語句使用關聯查詢替代子查詢,時間縮短爲30ms

SELECT cg.group_id,COUNT(0) AS contact_count FROM tbl_contacts_group AS cg,tbl_contacts AS c,tbl_group_relation AS gr 
WHERE c.cont_id=cg.cont_id AND cg.group_id=gr.group_id AND gr.parent_id='42b8df1e-415f-45ed-bedc-6147df42bc85' AND is_display=1 AND  cont_level>='A' GROUP BY cg.group_id 

 

四、總結

數據庫優化的最佳效果

1.常用字段增加索引

2.拆分複雜語句

4.優化數據庫參數,適當增加相關參數的緩存空間

5.升級數據庫版本(在mysql5.6上,版本1的語句執行時間在2秒以內)

優化的方法

1.監控分析(MONYog是個好工具)獲取執行頻繁用時較長的語句

2.調優

3.重複第1步

 

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