優化思路
詳細的MySQL優化步驟如下:
- 檢查資料表結構,改善不完善設計
- 跑一遍主要業務,收集常用的資料庫查詢SQL
- 分析查詢SQL,適當拆分,新增索引等優化查詢
- 優化SQL的同時,優化程式碼邏輯
- 新增本地快取和redis快取
儘可能不要使用NULL值
因為建表的時候,如果不對建立的值設定預設值,MySQL都會設定預設為NULL
。那麼為啥用NULL
不好呢?
NULL
使得索引維護更加複雜,強烈建議對索引列設定NOT NULL
NOT IN
、!=
等負向條件查詢在有NULL
值的情況下返回永遠為空結果,查詢容易出錯NULL
列需要一個額外位元組作為判斷是否為NULL
的標誌位- 使用
NULL
時和該列其他的值可能不是同種型別,導致問題。(在不同的語言中表現不一樣) - MySQL難以優化對可為
NULL
的列的查詢
所以對於那些以前偷懶的欄位,手動設定一個預設值吧,空字串呀,0呀補上。
雖然這種方法對於MySQL的效能來說沒有提升多少,但是這是一個好習慣,而且以小見大,不要忽略這些細節。
新增索引
對於經常查詢的欄位,請加上索引,有索引和沒有索引的查詢速度相差十倍甚至更多。
- 一般來說,每張表都需要有一個主鍵
id
欄位 - 常用於查詢的欄位應該設定索引
varchar
型別的欄位,在建立索引的時候,最好指定長度- 查詢有多個條件時,優先使用具有索引的條件
- 像
LIKE
條件這樣的模糊搜尋對於欄位索引是無效的,需要另外建立關鍵詞索引來解決 - 請儘量不要在資料庫層面約束表和表之間的關係,這些表之間的依賴應該在程式碼層面去解決
當表和表之間有約束時,雖然增刪查的SQL語句變簡單了,但是帶來的負面效果是插入等運算元據庫都會去檢查約束(雖然可以手動設定忽略約束),這樣相當於把一些業務邏輯寫到了資料庫層,不便於維護。
優化表欄位結構
資料庫中那些可以用整形表示的資料就不要使用字串型別,到底是用varchar
還是char
要看欄位的可能值。
這種優化往往在資料庫中有大量資料以後是不可行的,最好在資料庫設計之前就設計好。
- 對於那些可能值很有限的列,使用
tinyint
代替VARCHAR
,- 比如記錄移動裝置平臺,只有兩個值:android,ios,那麼就可以使用0表示android,1表示ios,這種列一定要寫好註釋
- 為什麼不用
ENUM
呢?ENUM
擴充套件困難,比如後來移動平臺又增加了一個ipad
,那豈不是懵逼了,而tinyint
加個2就行,而且ENUM
在程式碼裡面處理起來特別奇怪,是當成整形呢還是字串,各個語言不一樣。 - 這種方式,一定要在資料庫註釋或者程式碼裡面寫明各個值的含義
- 對於那些定長字串,可以使用
char
,比如郵編,總是5位 - 對於那些長度未知的字串,使用
varchar
- 不要濫用
bigint
,比如記錄文章數目的表id
欄位,用int
就行了,21億篇文章上限夠了 - 適當打破資料庫正規化新增冗餘欄位,避免查詢時的表連線
查詢的時候,肯定int
型別比varchar
快,因為整數的比較直接呼叫底層運算器就可以實現,而字串比較要逐個字元比較。
定長資料比變長資料查詢快,因為比較定長資料與資料之間的偏移是固定的,很容易計算下一個資料的偏移。而變長資料則還需要多一步去查詢下一個資料的偏移量。不過。定長資料可能會浪費更多的儲存空間。
大表拆分
對於那些資料量可能近期會超過500W或者增長很快的表,一定要提前做好垂直分表或者水平分表,當資料量超過百萬以後,查詢速度會明顯下降。
分庫分表儘量在資料庫設計初期敲定方案,否則後期會極大增加程式碼複雜性而且不易更改。
垂直分表是按照日期等外部變數進行分表,水平分表是按照表中的某些欄位關係,使用hash對映等分表。
分庫分表的前提條件是在執行查詢語句之前,已經知道需要查詢的資料可能會落在哪一個分庫和哪一個分表中。
優化查詢語句
這個才是很多系統資料庫瓶頸的始作俑者。
- 請儘量使用簡單的查詢,避免使用錶連結
- 請儘量避免全表掃描,會造成全表掃描的語句包括但不限於:
- where子句條件恆真或為空
- 使用
LIKE
- 使用不等操作符(<>、!=)
- 查詢含有
is null
的列 - 在非索引列上使用
or
- 多條件查詢時,請把簡單查詢條件或者索引列查詢置於前面
- 請儘量指定需要查詢的列,不要偷懶使用select *
- 如果不指定,一方面會返回多餘的資料,佔用寬頻等
- 另一方面MySQL執行查詢的時候,沒有欄位時會先去查詢表結構有哪些欄位
- 大寫的查詢關鍵字比小寫快一點點
- 使用子查詢會建立臨時表,會比連結(JOIN)和聯合(UNION)稍慢
- 在索引欄位上查詢儘量不要使用資料庫函式,不便於快取查詢結果
- 當只要一行資料時,請使用LIMIT 1,如果資料過多,請適當設定LIMIT,分頁查詢
- 千萬不要 ORDER BY RAND(),效能極低
新增快取
使用redis等快取,還有本地檔案快取等,可以極大地減少資料庫查詢次數。快取這個東西,一定要分析自己系統的資料特點,適當選擇。
- 對於一些常用的資料,比如配置資訊等,可以放在快取中
- 可以在本地快取資料庫的表結構
- 快取的資料一定要注意及時更新,還有設定有效期
- 增加快取務必會增加系統複雜性,一定要注意權衡
檢查資料表結構
本作品採用《CC 協議》,轉載必須註明作者和本文連結