慢sql總結

前置條件背景:某項目線上環境有短信、郵件、站內信、APP消息推送服務,例如短信在線上環境發一次可能是60w的發送記錄...等等,每種推送消息的渠道數據庫中可能會記錄上百萬、千萬的發送記錄(開發也採用分庫分表)。針對這些記錄後端進行統計查詢後前端展示報表數據。

 

 

解決辦法:從查詢方式由後端改爲數倉查詢

測試場景考慮:測試環境的可能因爲測試數據較少,而我們需要考慮到生產環境的數據量,針對於發送記錄較多的場景,判斷查詢方式是否合理,是否在時間久的情況下數據量過多而造成的慢sql

QA:

1、業務庫採用分庫分表,數倉需要怎樣去統計

答:對於數倉來說沒有影響

2、怎樣驗證慢sql優化效果

答:數倉查詢前一天的數據,而且後端在查詢的數倉ads結果表數據的時候,數倉已經把結果放在數據庫中了,相當於後端單表查每天的數據量且按照緯度加和。之前後端自己去查詢,查的是sql上萬的數據,如果沒有定時任務,或者每天通過sql去查詢,數據量是很大的,sql就肯定會慢,影響cpu資源,響應時間等。相當於數倉有臨時表緩存中間的結果,避免多次查詢主表,也減少了阻塞,提高性能。以前走數據庫的時候10W的數據量我們需要通過SQL去查詢統計之後返回給前端顯示,現在走數倉了之後我們相當於只是查我們已經統計好的某幾條數據,這樣對於我們來說不管是10W的數據量還是100W的數據量,都是走數倉了,而我們要查的只是統計表裏面的其中某幾條數據,對於我們服務器來說是沒有多少壓力的。

3、影響因素可能有哪些?

(1)數據量:數據量越大需要的I/O次數越多

(2)取數據的方式,數據在緩存中還是在磁盤上;是否可以通過索引快速尋址

(3)數據加工的方式,排序、子查詢等,需要先把數據取到臨時表中,再對數據進行加工;增加了I/O,且消耗大量CPU資源

(4)、沒有索引或則無效索引導致的全表掃描

4、針對慢sql有沒有好的解決思路?

(1)將數據存放在更快的地方。如果數據量不大,變化頻率不高,但訪問頻率很高,此時應該考慮將數據放在應用端的緩存當中或者Redis這樣的緩存當中,以提高存取速度。如果數據不做過濾、關聯、排序等操作,僅按照key進行存取,且不考慮強一致性需求,也可考慮選用NoSQL數據庫。

(2)適當合併I/O。分別執行select c1 from t1與select c2 from t1,與執行select c1,c2 from t1相比,後者開銷更小。合併時也需要考慮執行時間的增加。

(3)利用分佈式架構。在面對海量的數據時,通常的做法是將數據和I/O分散到多臺主機上去執行。

(4)OLTP環境下通常使用innodb引擎。索引使用b+tree.

(5)通過explain sql獲取的信息:第一個執行查詢的表;索引的使用情況;每張表掃描到的數據條數;

(6)通過select count(distinct cl)/count(1) from table,來查詢關鍵查詢字段的選擇性。越大說明選擇性越高,這種字段就應該優先建立索引。

(7)analyze table 根據情況,分析table使其索引重建或則分佈更加均衡。

(8)如果查詢優化後,反應出來的數據仍然很多,查詢很慢。這時就應該根據業務來調整查詢條件。

索引無效:

1、表關聯查詢時,字段類型或長度不一致。如:varchar(10)和varchar(20)

2、查詢參數的數據類型與索引字段類型不一致。如int = '1313'

3、in () 索引字段in查詢時,通常是有效的。但是當in中指定的數據太多,優化器認爲全表掃描更快時,也不會使用索引。

4、其他如:like、索引上使用函數等使索引失效。導致全表掃描

索引:向有索引的表當中插入、更新、刪除數據時,都需要對索引進行相應操作, 因此索引越多,寫表效率越低。索引列的選擇需要注意列的離散度(唯一性)越高,越適合做索引。

複合索引:應考慮索引之間組合的順序,將離散度最高的列放在前面

索引列長度:InnoDB單列索引長度不能超過767bytes,複合索引是3072。InnoDB一個page的默認大小是16k。由於是Btree組織,要求葉子節點上一個page至少要包含兩條記錄(否則就退化鏈表了)。所以一個記錄最多不能超過8k。又由於InnoDB的聚簇索引結構,一個二級索引要包含主鍵索引,因此每個單個索引不能超過4k (極端情況,pk和某個二級索引都達到這個限制)。由於需要預留和輔助空間,扣掉後不能超過3500,取個“整數”就是(1024*3)。

sql的執行順序:from>join>on>where>group by>avg/sum>having>select>distinct>order by > limit

sql 優化之8個儘量:

1、在表中建立索引,優先考慮where、group by使用到的字段。

2、儘量避免使用select *,返回無用的字段會降低查詢效率。

3、儘量避免使用in 和not in,會導致數據庫引擎放棄索引進行全表掃描。

4、儘量避免使用or,會導致數據庫引擎放棄索引進行全表掃描。

6、儘量避免進行null值的判斷,會導致數據庫引擎放棄索引進行全表掃描。

5、儘量避免在字段開頭模糊查詢,會導致數據庫引擎放棄索引進行全表掃描。

7、儘量避免在where條件中等號的左側進行表達式、函數操作,會導致數據庫引擎放棄索引進行全表掃描。

8、當數據量大時,避免使用where 1=1的條件。通常爲了方便拼裝查詢條件,我們會默認使用該條件,數據庫引擎會放棄索引進行全表掃描。

 

 

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