1. 程式人生 > >MySQL高併發優化,效能調優要這麼來~

MySQL高併發優化,效能調優要這麼來~

一、資料庫結構的設計

表的設計具體注意的問題:

1、資料行的長度不要超過 8020 位元組,如果超過這個長度的話在物理頁中這條資料會佔用兩行從而造成儲存碎片,降低查詢效率。

2、能夠用數字型別的欄位儘量選擇數字型別而不用字串型別的(電話號碼),這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連接回逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。

3、對於不可變字元型別 char 和可變字元型別 varchar 都是 8000 位元組, char 查詢快,但是耗儲存空間,varchar 查詢相對慢一些但是節省儲存空間。在設計欄位的時候可以靈活選擇,例如使用者名稱、密碼等長度變化不大的欄位可以選擇 CHAR,對於評論等長度變化大的欄位可以選擇 VARCHAR。

4、欄位的長度在最大限度的滿足可能的需要的前提下,應該儘可能的設得短一些,這樣可以提高查詢的效率,而且在建立索引的時候也可以減少資源的消耗。

二、查詢的優化 

保證在實現功能的基礎上,儘量減少對資料庫的訪問次數 (可以用快取儲存查詢結果,減少查詢次數);通過搜尋引數,儘量減少對錶的訪問行數, 最小化結果集,從而減輕網路負擔;能夠分開的操作儘量分開處理,提高每次的響應速度;在資料視窗使用 SQL 時,儘量把使用的索引放在選擇的首列;演算法的結構儘量簡單;在查詢時,不要過多地使用萬用字元如 SELECT * FROM T1 語句,要用到幾列就選擇幾列如:SELECTCOL1,COL2 FROM T1;在可能的情況下儘量限制儘量結果集行數如:SELECT TOP 300 COL1,COL2,COL3 FROM T1, 因為某些情況下使用者是不需要那麼多的資料的。

1. 應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:

  1. select id from t where num isnull

可以在 num 上設定預設值 0,確保表中 num 列沒有 null 值,然後這樣查詢:

  1. select id from t where num=0 

2. 應儘量避免在 where 子句中使用!= 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數, 因此需要搜尋該表的所有行。

3. 應儘量避免在 where 子句中使用 or 來連線條件,否則將導致引擎放棄使用索引而進行全表掃描,如:

  1. select id from t where num=10 or num=20 

可以這樣查詢:

  1. select id from t where num=10 
  2. unionall
  3. select id from t where num=20 

4.in 和 not in 也要慎用,因為 IN 會使系統無法使用索引, 而只能直接搜尋表中的資料。如:

  1. select id from t where num in(1,2,3) 

對於連續的數值,能用 between 就不要用 in 了:

  1. select id from t where num between 1 and 3 

5. 儘量避免在索引過的字元資料中,使用非打頭字母搜尋。這也使得引擎無法利用索引。

見如下例子:

  1. SELECT * FROM T1 WHERENAMELIKE ‘%L%’  
  2. SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’  
  3. SELECT * FROM T1 WHERENAMELIKE ‘L%’  

即使 NAME 欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有資料逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。

6.  必要時強制查詢優化器使用某個索引,如在 where 子句中使用引數,也會導致全表掃描。因為 SQL 只有在執行時才會解析區域性變數,但優化程式不能將訪問計劃的選擇推遲到執行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:

  1. select id from t where [email protected] 

可以改為強制查詢使用索引:

  1. select id from t with(index(索引名)) where [email protected] 

7.  應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:

  1. SELECT * FROM T1 WHERE F1/2=100  

應改為:

  1. SELECT * FROM T1 WHERE F1=100*2 
  2. SELECT * FROM RECORD WHERESUBSTRING(CARD_NO,1,4)=’5378’  

應改為:

  1. SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’ 
  2. SELECT member_number, first_name, last_name FROM members 
  3. WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21  

應改為:

  1. SELECT member_number, first_name, last_name FROM members  
  2. WHERE dateofbirth <DATEADD(yy,-21,GETDATE())  

即:任何對列的操作都將導致表掃描,它包括資料庫函式、計算表示式等等,查詢時要儘可能將操作移至等號右邊。

8.  應儘量避免在 where 子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。如:

  1. select id from t wheresubstring(name,1,3)='abc'--name 以 abc 開頭的 id
  2. select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的 id

應改為:

  1. select id from t wherenamelike'abc%'
  2. select id from t where createdate>='2005-11-30'and createdate<'2005-12-1'

9.  不要在 where 子句中的 “=” 左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。

10.  在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。

11.  很多時候用 exists 是一個好的選擇:

  1. select num from a where num in(select num from b) 

用下面的語句替換:

  1. select num from a where exists(select 1 from b where num=a.num) 
  2. SELECTSUM(T1.C1)FROM T1 WHERE
  3. (SELECTCOUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)  
  4. SELECTSUM(T1.C1) FROM T1WHERE EXISTS(  
  5. SELECT * FROM T2 WHERE T2.C2=T1.C2)  

兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。

如果你想校驗表裡是否存在某條紀錄,不要用 count(*) 那樣效率很低,而且浪費伺服器資源。可以用 EXISTS 代替。如:

  1. IF (SELECTCOUNT(*) FROM table_name WHERE column_name = 'xxx')  

可以寫成:

  1. IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx'

經常需要寫一個 T_SQL 語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:

  1. SELECT a.hdr_key FROM hdr_tbl a---- tbl a 表示 tbl 用別名 a 代替 
  2. WHERENOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key) 
  3. SELECT a.hdr_key FROM hdr_tbl a  
  4. LEFTJOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key ISNULL
  5. SELECT hdr_key FROM hdr_tbl  
  6. WHERE hdr_key NOTIN (SELECT hdr_key FROM dtl_tbl)  

12. 儘量使用表變數來代替臨時表。如果表變數包含大量資料,請注意索引非常有限(只有主鍵索引)。

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

14. 臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個資料集時。但是,對於一次性事件,最好使用匯出表。

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

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

17. 在所有的儲存過程和觸發器的開始處設定 SET NOCOUNT ON ,在結束時設定 SET NOCOUNT OFF 。無需在執行儲存過程和觸發器的每個語句後向客戶端傳送 DONE_IN_PROC 訊息。

18. 儘量避免大事務操作,提高系統併發能力。

19. 儘量避免向客戶端返回大資料量,若資料量過大,應該考慮相應需求是否合理。

20. 避免使用不相容的資料型別。例如 float 和 int、char 和 varchar、binary 和 varbinary 是不相容的(條件判斷時)。資料型別的不相容可能使優化器無法執行一些本來可以進行的優化操作。例如:

  1. SELECTnameFROM employee WHERE salary > 60000  

在這條語句中, 如 salary 欄位是 money 型的, 則優化器很難對其進行優化, 因為 60000 是個整型數。我們應當在程式設計時將整型轉化成為錢幣型, 而不要等到執行時轉化。

21. 充分利用連線條件(條件越多越快),在某種情況下,兩個表之間可能不只一個的連線條件,這時在 WHERE 子句中將連線條件完整的寫上,有可能大大提高查詢速度。

例:

  1. SELECTSUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO 
  2. SELECTSUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO 

第二句將比第一句執行快得多。

相關推薦

MySQL併發優化效能調這麼~

一、資料庫結構的設計 表的設計具體注意的問題: 1、資料行的長度不要超過 8020 位元組,如果超過這個長度的話在物理頁中這條資料會佔用兩行從而造成儲存碎片,降低查詢效率。 2、能夠用數字型別的欄位儘量選擇數字型別而不用字串型別的(電話號碼),這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎

併發服務 系統引數調相關

(*)系統引數 1、訊息佇列大小 和 可開啟檔案數 設定 /etc/sysctl.conf中增加以下配置 kernel.msgmni=1000 kernel.msgmax=81920 kernel.msgmnb=1638400   #fs.mqueue.msg_max=1000 #f

併發優化實踐】10倍請求壓力你的系統會被擊垮嗎?【石杉的架構筆記】

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! “ 上篇文章 一次 JVM FullGC的背後,竟隱藏著驚心動魄的線上生產事故!,給大家講了一個線上系統因為JVM FullGC異常宕機的case。 這篇文章,我們繼續給大家聊聊另

Mysql併發優化

一、資料庫結構的設計如果不能設計一個合理的資料庫模型,不僅會增加客戶端和伺服器段程式的程式設計和維護的難度,而且將會影響系統實際執行的效能。所以,在一個系統開始實施之前,完備的資料庫模型的設計是必須的。在一個系統分析、設計階段,因為資料量較小,負荷較低。我們往往只注意到功能的

MQ併發量時的調引數設定說明

高可用(主從)與負載均衡架構圖 訊息傳送中的接收Topic訂閱結果訊息佇列URL地址、訊息接收佇列URL地址、訊息代理的傳送與接收佇列URL地址以及訊息轉發器傳送的Topic結果訊息佇列URL地址,均需設定為Failover 地址。 由於訊息佇列元件ActiveMQ是

MySQL並行寫入、查詢效能調(多核CPU)

[html] view plain copy [client] port = 3306 socket = /tmp/mysql.sock [mysqld] port = 3306 socket = /tmp/mysql.sock based

liunx 優化效能調

cpu 效能瓶頸  計算機中,cpu是最重要的一個子系統,負責所有計算任務; 基於摩爾定律的發展,cpu是發展最快的一個硬體,所以瓶頸很少出現在cpu上; 我們線上環境的cpu都是多核的,並且基於SMP(symmetric multiprocessing)結構的。 通

Spring Cloud Feign 總結問題注意點效能調切換okhttp3

### Feign常見問題總結 **FeignClient介面如使用`@PathVariable` ,必須指定value屬性** ```java //在一些早期版本中, @PathVariable("id") 中的 "id" ,也就是value屬性,必須指定,不能省略。 @FeignClient("micro

網站併發優化效能調總結

最近在對PHP網站高併發高效能有所領悟,今天寫一篇關於這方面的文章。今天用我的測試站點:http://zhimo.yuanzhumuban.cc/來講解例項。 支模網整體開發到上線為10個月左右,後端採用php開源框架destoon,站點總資料為800萬,其中每天會更新入庫資料5000-50000資料不等,

Tomcat併發優化修改service.xml效能調 增加最大併發連線數

可以在控制檯的啟動資訊裡看見,預設狀態下沒有被開啟nio配置,啟動時的資訊,如下: 2010-2-1 12:59:40 org.apache.coyote.http11.Http11Protocol init 資訊: Initializing Coyote HTTP/1.1 on http-8080 2010

MySQL效能優化總結___本文乃《MySQL效能調與架構設計》讀書筆記!

一、MySQL的主要適用場景 1、Web網站系統 2、日誌記錄系統 3、資料倉庫系統 4、嵌入式系統 二、MySQL架構圖:   三、MySQL儲存引擎概述 1)MyISAM儲存引擎 MyISAM儲存引擎的表在資料庫中,每一個表

mysql效能調筆記(二)--查詢優化和索引

一、Mysql執行查詢流程                                                                           mysql執行查詢的流程 mysql執行查詢內部路程:1.客服端傳送一條查詢給伺服器

效能調MySQL篇三:MySQL配置定位以及優化

1、優化方式 一般的優化方法有:硬體優化,配置優化,sql優化,表結構優化。下面僅僅介紹配置優化,具體優化設定可以參考本人另外一篇部落格,傳送門:https://www.cnblogs.com/langhuagungun/p/9507206.html 2、mysql配置分析 1)常見瓶頸 90%系統瓶

效能調MySQL篇四:MySQL配置定位以及優化

一、CPU最大效能模式 cpu利用特點 5.1 最高可用4個核 5.5 最高可用24核 5.6 最高可用64核心 一次query對應一個邏輯CPU 你仔細檢查的話,有些伺服器上會有的一個有趣的現象:你cat /proc/cpuinfo時,會發現CPU的頻率竟然跟它標

mysql 併發調

最近做的一個應用,功能要求非常簡單,就是 key/value 形式的儲存,簡單的 INSERT/SELECT,沒有任何複雜查詢,唯一的問題是量非常大,如果目前投入使用,初期的單表 insert 頻率約 20Hz(次/秒,我喜歡這個單位,讓我想起國內交流電是 50Hz),但

MySQL效能調——索引詳解與索引的優化

——索引優化,可以說是資料庫相關優化、理解尤其是查詢優化中最常用的優化手段之一。所以,只有深入索引的實現原理、儲存方式、不同索引間區別,才能設計或使用最優的索引,最大幅度的提升查詢效率! 一、BTree索引 1、概述 Mysql資料庫中使用最頻繁的索引型別,基本所有儲存引

MySQL效能調——鎖定機制與鎖優化分析

——針對多執行緒的併發訪問,任何一個數據庫都有其鎖定機制,它的優劣直接關係著資料的一致完整性與資料庫系統的高併發處理效能。鎖定機制也因此成了各種資料庫的核心技術之一。不同資料庫儲存引擎的鎖定機制是不同

linux下修改核心引數進行Tcp效能調 -- 併發

前言: Tcp/ip協議對網路程式設計的重要性,進行過網路開發的人員都知道,我們所編寫的網路程式除了硬體,結構等限制,通過修改Tcp/ip核心引數也能得到很大的效能提升, 下面就列舉一

主從同步、讀寫分離、mysql效能調(軟優化)

 配置mysql主從同步1 主從同步的作用:讓slave身份的資料庫伺服器自動同步 master身份的資料庫伺服器上的資料。 一、主資料庫伺服器的配置192.168.4.121 使用者授權mysql> grant replication slave on *.* to [email

線上Redis併發效能調實踐

專案背景   最近,做一個按優先順序和時間先後排隊的需求。用 Redis 的 sorted set 做排隊佇列。   主要使用的 Redis 命令有, zadd, zcount, zscore, zrange 等。   測試完畢後,發到線上,發現有大量介面請求返回超時熔斷(超時時間為3s)。   Error日