從業這些年,帶過不少人、也接觸過很多同事同行,發現新人甚至工作很多年的同事,對MySQL的部分原理都有相似的錯誤理解。
本文會持續整理出一些常見誤區,希望能對大家的工作學習有幫助。
MySQL版本:5.6/5.7/8.x
真相列表
類型選擇和字段設計
INT長度並不能指定
常見的int(4)
並不是指最大存儲9999,而是低於4位的數字會使用空格或0在左側補齊到4位。這個4是顯示寬度。
int
實際上是定長字段,佔用4字節。取值範圍固定是-(231-1) ~ (231-1) ,無符號時爲0 ~ (232-1)。
延伸閱讀:
VARCHAR存儲的是字符而不是字節,但最大長度是另外的算法
VARCHAR
聲明的是字符數,但存儲的是字節。
理論上最大長度是65535 bytes,但實際上往往達不到。因爲有幾個因素:
-
65535是單行數據的最大值,實際上除了
varchar
,表裏應該還會有其他字段 -
varchar
存放的字符串,往往會有多字節字符、一個字符佔多個字節,而我們前端展現計算長度往往用的是字符數,所以也肯定達不到65535 -
varchar字段有長度標識位,可能佔用1~2個字節,與我們聲明的字段長度、字符集單字符最大長度有關,換算關係比較複雜,一句話說不清楚。
延伸閱讀:
自增不一定連續,還可能重複
首先傳遞一個邏輯,MySQL InnoDB
的自增,是使用了一個表級的計數器。
自增不一定連續:如果insert或update指定了比當前最大值更大的值,計數器會直接增加到新的最大值;如果delete已有的一行數據,計數器並不會減小。
自增可能重複:上面提到的計數器,是維護在內存中的,MySQL一旦重啓、又沒有手工重新裝載過計數器,新插入記錄自增主鍵就會重新從最小值開始,就會出現重複。
TIMESTAMP只能表達68年
TIMESTAMP
以4字節整數(可看做SIGNED INT
)存儲從1970-01-01T00:00:00Z
(UNIX紀元)經過的秒數。UNIX紀元看做0
值,小於紀元的時間插入會報錯。
有符號4字節
可以表達最大絕對值爲2^31-1
的數字,所以TIMESTAMP
的只能表達1970-01-01T00:00:01Z ~ 2038-01-19T03:14:07Z
的範圍。
函數使用
count(column)
不會統計所有行
count(column)
會忽略掉值爲NULL
的行,相比於count(*)
或count(1)
,統計出來的數字可能會小一些。從性能角度也不建議使用列。
更多
NULL
運算介紹和樣例可參考《NULL如何參與運算和統計》
以上。感謝您的閱讀。
持續更新中:
- 更多已知的MySQL誤區
- 字符集問題
- 不走索引(掃描比)
- 掃描導致的更新慢
- 等等
- 讀者反饋問題