MySQL資料庫優化

2022-06-11 18:24:13 字數 3823 閱讀 3327

「那啥,你過來一下!」

「怎麼了?我**都單元測試了的,沒出問題啊!」我一臉懵逼跑到運維大佬旁邊。

「你看看!你看看!多少條報警,趕快優化一下!」

運維大佬簡訊列表裡面好多mysql cpu 100%報警簡訊。再看看專案名稱不就是我前幾天剛發布的專案嗎!?

我心底一沉,趕快賠上笑臉。「這個一定優化,馬上優化!那個,能不能看下資料庫監控日誌…」

運維大佬又數落了我幾句,然後調開了資料庫監控日誌。

那傢伙…每秒300多的連線數,幾乎快要封頂的全表掃瞄數,還有大紅色cpu警報。。。

「那個,能不能看看nginx訪問日誌…我看下訪問量…」我弱弱地說到。

運維大佬不情願的跑了下下面的語句:

grep -c come access.log
shell

come這個介面是其中乙個請求量比較大的介面,結果是600多萬。那個時候才中午,週末高峰期估計一天得有上千萬吧!

我撇了撇嘴,心裡想著這麼高的請求量,當初那麼摳門只給我一台低配資料庫還好意思說,不過嘴上肯定是:「好好好,請求量不是很大,看來是資料庫問題,我立刻去優化一下!」

「給它弄乙個讀寫分離不就行了嗎!?」這時另外乙個運維大佬湊了過來,隨意地揮了揮手。。。

你問我dba去哪兒了?dba當時有點忙,只說讓我自己檢查一下。。。

我這個專案由於上線之前比較趕,所以前期並沒有管資料庫設計方面的一些問題,如今隨著遊戲接入,請求量劇增才暴露出來。(其實是前期加班加煩了懶得搞)

這個問題,並不需要增加資料庫硬體配置和增加讀寫分離這種高階手段就能解決,我自個兒挖了多少坑,心裡還是有點碧樹的。

詳細的mysql優化步驟如下:

這個專案是原生php寫的,以上這些只能自己做了。

因為比較菜,回去看設計的表結構,真是慘不忍睹。

因為建表的時候,如果不對建立的值設定預設值,mysql都會設定預設為null。那麼為啥用null不好呢?

所以對於那些以前偷懶的字段,手動設定乙個預設值吧,空字串呀,0呀補上。

雖然這種方法對於mysql的效能來說沒有提公升多少,但是這是乙個好習慣,而且以小見大,不要忽略這些細節。

對於經常查詢的字段,**上索引,有索引和沒有索引的查詢速度相差十倍甚至更多。

當表和表之間有約束時,雖然增刪查的sql語句變簡單了,但是帶來的負面效果是插入等運算元據庫都會去檢查約束(雖然可以手動設定忽略約束),這樣相當於把一些業務邏輯寫到了資料庫層,不便於維護。

資料庫中那些可以用整形表示的資料就不要使用字串型別,到底是用varchar還是char要看字段的可能值。

這種優化往往在資料庫中有大量資料以後是不可行的,最好在資料庫設計之前就設計好。

對於那些定長字串,可以使用char,比如郵編,總是5位

對於那些長度未知的字串,使用varchar

不要濫用bigint,比如記錄文章數目的表id字段,用int就行了,21億篇文章上限夠了

適當打破資料庫正規化新增冗餘字段,避免查詢時的表連線

查詢的時候,肯定int型別比varchar快,因為整數的比較直接呼叫底層運算器就可以實現,而字串比較要逐個字元比較。

對於那些資料量可能近期會超過500w或者增長很快的表,一定要提前做好垂直分表或者水平分表,當資料量超過百萬以後,查詢速度會明顯下降。

分庫分表盡量在資料庫設計初期敲定方案,否則後期會極大增加**複雜性而且不易更改。

垂直分表是按照日期等外部變數進行分表,水平分表是按照表中的某些字段關係,使用hash對映等分表。

分庫分表的前提條件是在執行查詢語句之前,已經知道需要查詢的資料可能會落在哪乙個分庫和哪乙個分表中。

這個才是很多系統資料庫瓶頸的始作俑者。

多條件查詢時,請把簡單查詢條件或者索引列查詢置於前面

請盡量指定需要查詢的列,不要偷懶使用select *

大寫的查詢關鍵字比小寫快一點點

使用子查詢會建立臨時表,會比鏈結(join)和聯合(union)稍慢

在索引欄位上查詢盡量不要使用資料庫函式,不便於快取查詢結果

當只要一行資料時,請使用limit 1,如果資料過多,請適當設定limit,分頁查詢

千萬不要 order by rand(),效能極低

上面是我總結的一些小tips,這些規則是死的,但是業務場景是活的,在實際使用的過程中,比如資料統計,可以適當犧牲效能換取便利。

使用redis等快取,還有本地檔案快取等,可以極大地減少資料庫查詢次數。快取這個東西,一定要分析自己系統的資料特點,適當選擇。

下面舉幾個簡單的優化查詢例子。首先就是跑一下主要業務,把主要的查詢語句列印到乙個檔案裡面,然後分析這些語句。

補充一下,在查詢語句前使用關鍵字explain可以檢視查詢執行的具體情況。

看下面的這個查詢語句

select

*from link

where player_id=

'15298635'

and gameid=

'10389'

'200'

andaction

='open'

and creator=

'android_sdk'

and transport=

''

sql

上面這條語句毛病挺多的

顯然查詢條件很多,而且很多列都是不定長的varchar型別,如果要建立索引,是不是要建立聯合索引呢?

這樣的查詢語句要結合具體的業務場景來進行分析,比如在我當前的系統中,我是期望上面的語句能夠查詢相同的引數下是否有記錄。其實沒必要使用這麼多條件的查詢。

我只需要使用下面的這條更簡單的查詢語句代替即可。

select id,player_id

from link

where player_id=

'15298635'

sql

查詢到的記錄條數在100條以下,大部分就只用幾十條記錄,我完全可以在**裡面在把查詢結果遍歷一遍判斷即可。這樣不知道有多快呢!

再看下面的這個例子:

select

*from browser

where device_id=

'52'

and created>=

'1513735322'

order

by id desc

sql

我只是想查一下這個表裡面某個時間以後的資料。問題大了!

created欄位是timestamp型別,這樣用是不對的,而且沒有限定行數,這條語句會把資料庫所有的device_id=』52』的資料搞出來。

還好device_id字段設定了索引,要不然必然會導致全表掃瞄。

修改後的查詢如下:

select

*from browser

where device_id=

'52'

and created>=

'2018-03-27 00:00:00'

order

by id desc

sql

我的專案中並沒有使用複雜的像表連線和聯合這樣的查詢,這類查詢一定要謹慎使用,能夠拆分的話盡量拆分。

記住下面的速度優先順序,兩兩之間相差2個以上數量級

cpu執行速度 > 記憶體訪問速度 > 磁碟io訪問速度 > 網路請求速度

mysql資料庫優化索引 mysql資料庫索引調優

一 mysql索引 1 磁碟檔案結構 innodb引擎 frm格式檔案儲存表結構,ibd格式檔案儲存索引和資料。myisam引擎 frm格式檔案儲存表結構,myi格式檔案儲存索引,myd格式檔案儲存資料 2 mysql資料庫資料範問原理 innodb btree 1 ibd檔案中主鍵構建b tree...

mysql資料庫優先 MySQL資料庫優化

1.新增索引 mysql資料庫的四類索引 index 普通索引,資料可以重複,沒有任何限制。unique 唯一索引,要求索引列的值必須唯一,但允許有空值 如果是組合索引,那麼列值的組合必須唯一。primary key 主鍵索引,是一種特殊的唯一索引,乙個表只能有乙個主鍵,不允許有空值,一般是在建立表...

mysql資料庫優化

用到啥學啥,mysql資料庫優化成了這幾天的老大難問題。瘋狂的尋找mysql優化的資料,覺得有用的不少,記錄下跟大家分享,對了,這裡僅僅是mysql資料庫本身的優化,沒有寫磁碟之類的 開始之前,介紹倆mysql的命令 show global status 檢視執行狀態的,顯示執行各種狀態值 show...