Mysql學習總結(36)——Mysql查詢優化

從事前端開發的都知道,頁面顯示的數據一定要及時的呈現,否則會影響用戶體現.那麼導致頁面加載數據慢或者顯示滯後的原因又是什麼呢?

拿自己之前做項目經歷給大傢講講吧,之前做後臺,當時的項目實時性都非常高,前端頁面實時顯示要求非常高 ,慢1秒顯示都會導致用戶的投訴,最後沒辦法,通過本地(磁盤)緩存跟數據表分割來解決這一問題.

原因分析

主要原因1: 後臺資料庫中的數據過多,沒做數據優化導致後臺查詢數據很慢

次要原因2: 前端數據請求-解析-展示過程處理不當

次要原因3: 網絡問題所致

那麼我們應該怎麼做後臺數據優化呢?

解決問題

這裡總結瞭幾種方案,如何提高資料庫查詢的速度,大傢參考.

1、緩存,在持久層或持久層之上做緩存

使用ehcache緩存,這個一般用於持久層的緩存,提供持久層、業務層的快速緩存,hibenate默認使用的二級緩存就是ehcache;

2、資料庫表的大字段剝離

假如一個表的字段數有100多個,學會拆分字段,保證單條記錄的數據量很小;

3、恰當地使用索引

必要時建立多級索引,分析MySQL的執行計劃,通過表數據統計等方式協助資料庫走正確的查詢方式,該走索引就走索引,該走全表掃描就走全表掃描;

4、表的拆分

表分區和拆分,無論是業務邏輯上的拆分(如一個月一張報表、分庫)還是無業務含義的分區(如根據ID取模分區);

5、字段冗餘

減少跨庫查詢和大表連接操作;,數據通過單個或多個JOB生成出來,減少實時查詢;

6、從磁盤上做文章

數據存放的在磁盤的內、外磁道上,數據獲取的效率都是不一樣的;

7、放棄關系資料庫的某些特性

引入NoSQL資料庫;

換種思路存放數據,例如搜尋中的倒排表;

在上面談到資料庫查詢速度優化方案我們講到瞭,數據優化的幾種方案。接下來,一起看如何實際到具體的操作上.也就是我們在寫數據時我們應該註意些什麼?

1、對查詢進行優化,應盡可能避免全表掃描

首先應考慮在 where 及 order by 涉及的列上建立索引。

下面我們來以一個表中177條數據比較一下,全表掃描與建立索引之後性能的一個比較.

1.1 全表查詢

 

 

1.2 建立索引查詢

 

 

1.3 結論

從這兩種方式查詢資料庫結果看,建立索引之後查詢速度提高瞭些,現在數據量還不明顯,如果表中有10萬條速度,差異就會很明顯瞭.

2、寫數據語句時盡可能減少表的全局掃描

2.1 減少where 字段值null判斷

 

 

如何這樣做,就會導致引擎放棄使用索引而進行全表掃描

應該這樣去設置(也就是在沒有值時,我們在存資料庫時自動默認給個o值,而不是什麼都不寫):

 

 

2.2 應盡量避免在 where 子句中使用!=或<>操作符

 

 

這樣寫將導致引擎放棄使用索引而進行全表掃描。

2.3 應盡量避免在 where 子句中使用 or 來連接條件

 

 

這樣將導致引擎放棄使用索引而進行全表掃描

可以這樣操作:

 

 

2.4 in 和 not in 也要慎用

 

 

這樣操作,也會導致全表掃描

 

 

以通配符*去查詢所有數據,這樣做也是非常耗時的,我們應該需要什麼字段就查詢什麼字段.

應該這樣做:

3、不要在條件判斷時進行 算數運算

所以不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,這樣系統將可能無法正確使用索引

應該這樣做:

4、很多時候用 exists 代替 in 是一個好的選擇

 

 

5 論索引技巧

5.1 並不是所有索引對查詢都有效

SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建瞭索引也對查詢效率起不瞭作用。

5.2 索引並不是越多越好

索引固然可以提高相應的 select 的效率,但同時也降低瞭 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

5.3 應盡可能的避免更新 clustered 索引數據列

因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要考慮是否應將該索引建為 clustered 索引。

5.4 盡量使用數字型字段

若隻含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言隻需要比較一次就夠瞭。

6 創建資料庫時應該註意地方

6.1. 盡可能的使用 varchar/nvarchar 代替 char/nchar

因為首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜尋效率顯然要高些。

6.2 用表變量來代替臨時表。

1. 如果表變量包含大量數據,請註意索引非常有限(隻有主鍵索引)。

2. 在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為瞭緩和系統表的資源,應先create table,然後insert。

3. 如果使用到瞭臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

4. 避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

7. 盡量避免使用遊標

1. 因為遊標的效率較差,如果遊標操作的數據超過1萬行,那麼就應該考慮改寫。

2. 使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

3. 與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。

8 數據放回時註意什麼

8.1 盡量避免大事務操作,提高系統並發能力。

這樣可以有效提高系統的並發能力

8.2 盡量避免向客戶端返回大數據量

若數據量過大,應該考慮相應需求是否合理。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *