個人對於選擇存儲引擎,建表,建索引,sql優化的一些總結,給讀者提供一些參考意見
推薦訪問我的個人網站,排版更好看: https://chenmingyu.top/mysql-optimize/
存儲引擎
mysql中查看支持的引擎的sql:
show engines;
日常工作中使用較多的存儲引擎對比:InnoDB,MyISAM
InnoDB | MyISAM | |
---|---|---|
存儲限制 | 64T | 256T |
支持事務 | yes | no |
支持索引 | yes | yes |
支持全文索引 | no | yes |
支持數據緩存 | yes | no |
支持外鍵 | yes | no |
支持Hash索引 | no | no |
innodb
支持提交、回滾和崩潰恢復能力的事物安全(ACID),支持行鎖,支持外鍵完整性約束
適合場景
- 需要事務處理
- 表數據量大,高並發操作
MyISAM
MyISAM存儲引擎提供了高速檢索和存儲的能力,支持全文索引
適合場景
- 很多count計算的
- 查詢非常頻繁的
其余幾種存儲引擎
MEMORY引擎
數據只保存在內存中,因為是在內存中,擁有極高的插入,更新,查詢的效率,但是重啟后數據都會丟失,表級鎖,並發性能低。
MERGE引擎
merge表是一組MyISAM表的組合,所以merge表是沒有數據的,對這個表的操作實際上是操作內部的MyISAM表,將多個MyISAM表合並適合做一些報表之類的操作。
ARCHIVE引擎
僅支持插入和查詢,使用zlib壓縮庫,在記錄被請求的時候實時壓縮,不支持事務,支持行級鎖,適合存儲大量的日志數據。
個人是推薦Innodb引擎的,公司部門里也是規定新建表的時候必須使用Innodb引擎,Innodb引擎較MyISAM引擎可以提供更多的功能,不是很實時的查詢場景可以使用緩存,近實時的查詢可以使用es,當然了這只是個人看法,針對不同的場景選擇不同的存儲引擎還是很有必要滴。所以在知道不同存儲引擎的特性之后,才可以根據不同業務需求選擇合適的存儲引擎。
建表原則
在建表的時候盡量遵循以下原則
-
盡量選擇小的數據類型,數據類型選擇上盡量tinyint(1字節)>smallint(2字節)>int(4字節)>bigint(8字節),比如邏輯刪除yn字段上(1代表可用,0代表)就可以選擇tinyint(1字節)類型
-
盡量保證字段數據類型長度固定
-
盡量避免使用null,使用null的字段查詢很難優化,影響索引,可以使用0或''代替
-
避免寬表,能拆分就拆分,一個表往往跟一個實體域對應,就像設計對象的時候一樣,保持單一原則
-
盡量避免使用text和blob,如果非使用不可,將類型為text和blob的字段在獨立成一張新表,然后使用主鍵對應原表
-
禁止使用float或double類型,這個坑超大,float或double存在精度問題,在進行比較或者加減操作的時候會丟失精度導致數據異常,凡是使用float或double類型的時候考慮下可不可使用int或bigint代替。比如金額,以元為單位使用float或double類型的時候,可以考慮以分為單位使用int,bigint類型代替,然后由業務代碼進行單位的轉換。
-
每張表都加上createUser,createTime.updateUser,updateTime字段
-
起名字要規范,包括:庫名,表名,字段名,索引名
-
查詢頻繁使用的字段記得加索引
-
盡量避免使用外鍵,不用外鍵約束,性能更高,然后數據的完整性有程序進行管理
-
如果表的數量可以預測到非常大,最好在建表的時候,就進行分表,不至於一時間數據量非常大導致效率問題
未完待補充,,,
索引
索引是為來加速對表中數據行中的檢索而創建的一種分散的數據結果,是針對表而建立的,它是由數據頁面以外的索引頁面組成,每個索引頁中的行都含有邏輯指針,以便加速檢索物理數據,創建索引的目的在於提高查詢效率,innodb的索引都是基於b tree實現的
索引類型
普通索引:最基本的索引,無限制
#方式1
CREATE INDEX idx_username ON sys_user(user_name(32));
#方式2
ALTER table sys_user ADD INDEX idx_username(user_name(32))
主鍵索引:一個表只能有一個主鍵索引,且不能為空
一般建表時同時創建了主鍵索引
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(32) DEFAULT NULL,
`pass_word` varchar(32) DEFAULT NULL,
`token` varchar(32) DEFAULT NULL,
`token_expire` int(11) DEFAULT NULL,
`yn` smallint(6) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=348007 DEFAULT CHARSET=utf8;
唯一索引:與普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一
CREATE UNIQUE INDEX idx_token ON sys_user(token_expire)
組合索引:指多個字段上創建的索引,只有在查詢條件中使用了創建索引時的第一個字段,索引才會被使用。使用組合索引時遵循最左前綴集合
ALTER TABLE sys_user ADD INDEX idx_un_te (user_name(32),token_expire);
全文索引:用來查找文本中的關鍵字,而不是直接與索引中的值相比較。只有char、varchar,text 列上可以創建全文索引
CREATE FULLTEXT INDEX idx_ ON sys_user(pass_word)
創建使用索引的原則
- 索引的字段盡量要小,根據索引查詢數據的快慢取決於b tree的高度,當數據量恆定的時候,字節越少,存的索引的數量就越多,樹的高度就越會越低
- 遵循索引的最左匹配原則
- 注意使用like的時候盡量不要使用“%a%”,這樣的不走索引,可以使用“a%”,走索引
- 不要在索引的列上進行計算,比如 select * from sys_user where token_expire+1 = 10000,這樣的語句 不會走有索引
- 什么樣的字段建索引,就是那種頻繁在where,group by,order by中出現的列,最好加上索引
索引的缺點
雖然索引的可以提高查詢的效率,但是在進行insert,update,和delete的時候會降低效率,因為在保存數據的同時也會去保存索引。
不要在一個表里建過多的索引,問題跟上面一樣,在操作數據的時候效率降低,而且數據量少的表要看情況建索引,如果建索引跟沒建索引的效果差不多少的情況下就不要建索引了,如果是數據量大的表,就需要建索引去優化查詢效率。
explain分析sql
可以使用explain去分析sql的執行情況,比如
explain select * from sys_user where token_expire = 10000;
在阿里的開發手冊中提到過,sql性能優化的標准:至少要達到range,要求ref級別,如果可以是consts最好
說明一下,這里的級別指的就是上圖的type字段:
- consts 是指單表中最多只有一個匹配行(主鍵或唯一索引)
- ref 指的是使用普通索引
- range 是指對索引進行范圍查詢
sql優化
關於sql語句的優化主要是兩方面,一個是在建sql的時候需要注意的問題,另一個就是在發現有慢sql的時候可以根據不同情況進行分析,然后優化sql
優化的建議
-
查詢的時候一定要記得使用limit進行限制
-
對於結果只需要一條數據的查詢用limit 1進行限制
-
使用count(*)來統計行數或者使用count(主鍵)來查詢,使用count(列)的時候,不會統計此列為null的情況
-
不要使用select * 來查數據,使用select 需要的列名,這樣的方式去查詢
-
使用join鏈接代替子查詢
-
不要使用外鍵,外鍵的約束可以放在程序里解決
-
控制一下in操作的集合數量,不要太大了
-
針對慢查詢使用explain去分析原因,然后優化sql,讓其盡量走索引
上面說的四個方面就是我目前對於sql優化各個方面的注意事項,希望可以給大家提供一個參考,有問題的可以指出來,交流交流