MySQL 高併發優化

2021-09-02 21:20:14 字數 4881 閱讀 3336

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

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

select id from t where num is null

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

select id from t where num=0

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

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

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

可以這樣查詢:

select id from t where num=10

union all

select id from t where num=20

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

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

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

select id from t where num between 1 and 3

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

見如下例子:

select * from t1 where name like 『%l%』

select * from t1 where substing(name,2,1)=』l』

select * from t1 where name like 『l%』

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

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

select id from t where num=@num

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

select id from t with(index(索引名)) where num=@num

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

select * from t1 where f1/2=100

應改為:

select * from t1 where f1=100*2

select * from record where substring(card_no,1,4)=』5378』

應改為:

select * from record where card_no like 『5378%』

select member_number, first_name, last_name from members

where datediff(yy,datofbirth,getdate()) > 21

應改為:

select member_number, first_name, last_name from members

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

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

select id from t where substring(name,1,3)='abc'--name 以 abc 開頭的 id

select id from t where datediff(day,createdate,'2005-11-30')=0--『2005-11-30』生成的 id

應改為:

select id from t where name like 'abc%'

select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

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

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

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

elect num from a where num in(select num from b)

用下面的語句替換:

select num from a where exists(select 1 from b where num=a.num)

select sum(t1.c1)from t1 where(

(select count(*)from t2 where t2.c2=t1.c2>0)

select sum(t1.c1) from t1where exists(

select * from t2 where t2.c2=t1.c2)

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

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

if (select count(*) from table_name where column_name = '***')

可以寫成:

if exists (select * from table_name where column_name = '***')

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

select a.hdr_key from hdr_tbl a---- tbl a 表示 tbl 用別名 a 代替

where not exists (select * from dtl_tbl b where a.hdr_key = b.hdr_key)

select a.hdr_key from hdr_tbl a

left join dtl_tbl b on a.hdr_key = b.hdr_key where b.hdr_key is null

select hdr_key from hdr_tbl

where hdr_key not in (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 是不相容的(條件判斷時)。資料型別的不相容可能使優化器無法執行一些本來可以進行的優化操作。例如:

select name from employee where salary > 60000

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

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

例:select sum(a.amount) from account a,card b where a.card_no = b.card_no

select sum(a.amount) from account a,card b where a.card_no = b.card_no and a.account_no=b.account_no

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

高併發優化

前台優化 1 減少http請求 css檔案合併 js檔案合併 2 壓縮js css檔案 3 使用雪碧圖 4 懶載入 只載入看到的第一屏內容,下拉之後看到其他的內容 5 預載入 載入預設圖 6 避免css樣式表示式 7 避免空的src 8 調整大小 9 cdn加速 1 頁面靜態化 2 負載均衡 集群 ...

高併發優化

1 前台優化 減少http請求 css檔案合併 js檔案合併 壓縮js css檔案 使用雪碧圖 懶載入 只載入看到的第一屏內容,下拉之後看到其他內容 預載入 載入預設圖 避免css樣式表示式 cdn加速 2 服務端優化 頁面靜態化 負載均衡 集群 分布式使用佇列 3 優化 用單引號代替雙引號,雙引號...

高併發優化

1 資料庫裡不常變的資料,快取下來 2 盡量不用string,需要執行緒安全用stringbuffer,不需要執行緒安全用stringbuilder stringbuilder stringbuffer string 3 資料庫裡涉及併發操作的sql需要用資料庫事物執行 4 工具類 寫成靜態方法,不...