單條查詢最后添加 LIMIT 1,停止全表掃描。
對于char(4) 或者vachar(4),無論是中文還是英文都是存儲四個字符,注意是字符而不是字節。
如果一個字段未int類型,此類型只有0、1兩個狀態,需要為此建立索引嗎?過度索引,影響更新速度,必須在唯一性較高的字段上建立非聚集索引。
在創建表的時候如果在業務中能保證非null的字段,建議明確標示not null 因為mysql中對null需要特殊的標示。使用not null 字段更節省空間。對接下來的索引構建也有好處。
count() 和count(name) name 代表某個字段,可以為NULL。在mysql中count()會把null統計進去、而count(name) 不會。如果統計的字段中含有null,這個兩個統計的結果是不同的。
在sql語句等號左邊用函數,會使該查詢在該字段無法使用索引。如LENGTH(str) 函數。
索引也是需要存儲到物理空間的,經常增刪的表不適合建太多的索引,因為索引的維護會很耗時間。一張表最多建立15個索引。索引的長度越小越好,索引是有序的。如果查詢Max()之類用索引的話,連表都不用查詢了,快得飛起。
mysql中null不參與比較運算,name <>'小米' 得出的結果中不包含 name=null的情況。在業務不能保證某字段是否為null的情況,寫代碼的時候需要注意null的坑。保證取得的數據是對而全,然后再考慮查詢速率問題。
MySQL InnoDB默認行級鎖。行級鎖都是基于索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點需要注意。
對整數類型指定寬度,比如INT(11),沒有任何卵用。INT使用32位(4個字節)存儲空間,那么它的表示范圍已經確定,所以INT(1)和INT(20)對于存儲和計算是相同的。
UNSIGNED表示不允許負值,大致可以使正數的上限提高一倍。比如TINYINT存儲范圍是-128 ~ 127,而UNSIGNED TINYINT存儲的范圍卻是0 - 255。
通常來講,沒有太大的必要使用DECIMAL數據類型。即使是在需要存儲財務數據時,仍然可以使用BIGINT。比如需要精確到萬分之一,那么可以將數據乘以一百萬然后使用BIGINT存儲。這樣可以避免浮點數計算不準確和DECIMAL精確計算代價高的問題。
TIMESTAMP使用4個字節存儲空間,DATETIME使用8個字節存儲空間。因而,TIMESTAMP只能表示1970 - 2038年,比DATETIME表示的范圍小得多,而且TIMESTAMP的值因時區不同而不同。
schema的列不要太多。原因是存儲引擎的API工作時需要在服務器層和存儲引擎層之間通過行緩沖格式拷貝數據,然后在服務器層將緩沖內容解碼成各個列,這個轉換過程的代價是非常高的。如果列太多而實際使用的列又很少的話,有可能會導致CPU占用過高。
大表ALTER TABLE非常耗時,MySQL執行大部分修改表結果操作的方法是用新的結構創建一個張空表,從舊表中查出所有的數據插入新表,然后再刪除舊表。尤其當內存不足而表又很大,而且還有很大索引的情況下,耗時更久。