我的對於選擇存儲引擎,建表,建索引,sql優化的一些總結,給讀者提供一些參考意見mysql
推薦訪問個人我的網站,排版更好看: chenmingyu.top/mysql-optim…sql
mysql中查看支持的引擎的sql:緩存
show engines;
複製代碼
平常工做中使用較多的存儲引擎對比:InnoDB,MyISAM安全
InnoDB | MyISAM | |
---|---|---|
存儲限制 | 64T | 256T |
支持事務 | yes | no |
支持索引 | yes | yes |
支持全文索引 | no | yes |
支持數據緩存 | yes | no |
支持外鍵 | yes | no |
支持Hash索引 | no | no |
從MySQL5.6版本開始InnoDB已經支持建立全文索引了性能優化
支持提交、回滾和崩潰恢復能力的事物安全(ACID),支持行鎖,支持外鍵完整性約束bash
適合場景併發
MyISAM存儲引擎提供了高速檢索和存儲的能力,支持全文索引高併發
適合場景性能
其他幾種存儲引擎優化
數據只保存在內存中,由於是在內存中,擁有極高的插入,更新,查詢的效率,可是重啓後數據都會丟失,表級鎖,併發性能低。
merge表是一組MyISAM表的組合,因此merge表是沒有數據的,對這個表的操做其實是操做內部的MyISAM表,將多個MyISAM表合併適合作一些報表之類的操做。
僅支持插入和查詢,使用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的高度,當數據量恆定的時候,字節越少,存的索引的數量就越多,樹的高度就越會越低
好比:設置varchar(10),則這個索引創建的時候只會存字段前10個字節,字段設置的字節數比較小可能會致使索引查出來的數據多,進而進行回表,致使性能降低,因此字段設置爲多少仍是要本身斟酌一下
遵循索引的最左匹配原則
注意使用like的時候儘可能不要使用「%a%」,這樣的不走索引,可使用「a%」,走索引
不要在索引的列上進行計算,好比 select * from sys_user where token_expire+1 = 10000,這樣的語句 不會走有索引
什麼樣的字段建索引,就是那種頻繁在where,group by,order by中出現的列,最好加上索引
使用聯合索引的時候儘可能考慮到索引下推優化
對於使用or的條件,須要or左右的條件都是索引纔會走索引,不然走全表掃描,能夠考慮使用union代替
避免使用select *,對於只須要查詢主鍵或者where 條件中只有索引的字段, 這時會走覆蓋索引建少回表次數
sql語句中避免隱式轉換,在MySQL中,字符串和數字作比較的話,是將字符串轉換成數字,如字段是varchar類型,可是入參是int類型,即使字段有索引也不會走,由於這裏會進行一次隱式轉換
總之使用索引的時候,須要考慮的地方比較多,可是歸根結底就是查詢儘可能走索引,走索引儘可能避免回表或減小回表次數
雖然索引的能夠提升查詢的效率,可是在進行insert,update,和delete的時候會下降效率,由於在保存數據的同時也會去保存索引。
不要在一個表裏建過多的索引,問題跟上面同樣,在操做數據的時候效率下降,並且數據量少的表要看狀況建索引,若是建索引跟沒建索引的效果差很少少的狀況下就不要建索引了,若是是數據量大的表,就須要建索引去優化查詢效率。
可使用explain去分析sql的執行狀況,好比
explain select * from sys_user where token_expire = 10000;
複製代碼
在阿里的開發手冊中提到過,sql性能優化的標準:至少要達到range,要求ref級別,若是能夠是consts最好
說明一下,這裏的級別指的就是上圖的type字段:
關於sql語句的優化主要是兩方面,一個是在建sql的時候須要注意的問題,另外一個就是在發現有慢sql的時候能夠根據不一樣狀況進行分析,而後優化sql
count(*)
或count(1)來統計行數來查詢,使用count(列)的時候,須要在查看列中這個是否爲null,不會統計此列爲null的狀況,並且mysql已經對count(*)
作了優化上面說的四個方面就是我目前對於sql優化各個方面的注意事項,但願能夠給你們提供一個參考,有問題的能夠指出來,交流交流