优化MySQL数据类型——《深究MySQL》
1. 選擇數據類型總體原則
1.1 操作整型比字符簡單
??因為字符的字符集和校對規則(排序規則)使得字符的比較比整型的比較更為復雜。
??如我們應該用datetime、date或time存儲日期類型,而不是字符串。
??我們也應該用整型來存儲IP地址。
1.2 盡量避免Null
??NULL的列可使得索引、索引統計和值的比較都更復雜。
??可為NULL的列會占用更多的存儲空間,因為此時,每個索引記錄需要一個額外的字節
??通常情況下最好指定列為NOT NULL,除非真的需要NULL的值,一般改為NOT NULL帶來的性能提升比較小
??InnoDB使用單獨的位(bit)存儲NULL值,所以對于稀疏數據(大部分數據為NULL,只有少部分非空數據)有很好的空間效率。
2. 整數類型
2.1 整數類型有tinyint、smallint、mediumint、int、bigint
??它們分別使用8,16,24,32,64位存儲空間,它們的存儲范圍是?2(N?1)到2(N?1)?1,其中冪里的N是位數。
??unsigned(無符號)屬性不充許有負值,這可以使正數存儲范圍擴大一倍,如tinyint的范圍就會從-128~127變成0~255
??整數計算一般使用有64位的bigint整數,即使在32位的環境中即是如此
??對存儲和計算來講,指定了長度的int(1)和int(12)是相同的。因為這個指定的長度只是規定了交互工具(如MySQL命令客戶端)顯示字符的個數。而不是指定的存儲大小。這個規則只適用于像tinyInt這種數字類型而不適用于varchar和char類型。
3. 實數類型(帶有小數的數字)
3.1 Float和Double類型支持使用標準的浮點運算進行近似計算
3.2 Decimal類型用于存儲精確的小數
??decimal需要額外的空間和計算開銷,所以盡量只在需要對小數進行精確計算時使用(如與錢相關的數據)。
??在數量比較大的時候,可考慮使用bigint代替decimal。此時只需根據小數位數乘以相應的倍數即可。
4. 字符串類型
Varchar
4.1 varchar類型需要1~2個額外字節記錄字符串的長度;當列的最大長度<=255時,用1個;當>255時用2個字節。
4.2 varchar是可變長的,所以節省存儲空間;但如果在update時列變得比原來長,導致整行數據占用的空間增長,如果在頁內存不下時,InnoDB引擎就會做頁分裂這個額外的操作。
4.3 選擇varchar類型的情況
字符串列的最大長度比平均長度大很多
列的更新頻率較少
使用了像UTF-8這樣復要的字符集,每個字符集都使用不同的字節數進行存儲
4.4 InnoDB中會把過長的varchar存儲為BLOB
4.5 Varchar(100)后面的長度100指定是存儲長度,雖然它是變長的,但是也不能隨意往大了設置,因為在內存中會以這個長度大小的內存塊來存儲數據。
Char
4.6 當存儲Char值時,MySQL會刪除末尾的所有空格
4.7 Char適合存儲像MD5這種定長的字符串
4.8 利用Char(1)在存儲像只有Y和N的值時,比Varchar(1)節約空間,因為varchar還要一個字節記錄長度
4.9 Memeory引擎只支持定長的行,即使有變長字段,也會根據最大長度分配空間
Binary和VarBinary
這是二進制字符串
4.10 MySQL在填充Binary時用的是\0(零字節)而不是空格,在檢索時也不會去掉
4.11 MySQL在比較Binary字符串時,每次按一個字節,并且是根據該字節的數值進行比較;因此二進制比較比字符串的比較快。
Blob和Text
4.12 Blob和Text都是為存儲很大的數據而設計的,它們分別采用二進制和字符方式存儲
4.13 字符類型有TinyText、SmallText、Text、MediumText、LongText;對應的二進制類型:TinyBlob、SmallBlob、Blob、MediumBlob、LongBlob
4.14 與其他類型不同,每個Blob和Text值會被當成獨立的對象對象。當數據很大時,InnoDB會在外部存儲區域存儲,此時每個值在行內需要1~4個字節存儲指向外部存儲區域的指針。
4.15 Blob和Text在排序時,只對列中最前max_sort_length。如果只排序前面一小部分,則可以減小max_sort_length的值,或者使用order by substring(列名,length)
4.16 Blob和Text只能索引前端一小部分數據,好像是前256
Enum
4.17 枚舉類型非常緊湊
4.18 枚舉類型的底層是將枚舉的幾個值保存為整數,并且在表的.fm文件中保存“數字-字符串”映射關系的查找表。
4.19 枚舉中盡量不要存數字,不然容易引起歧義。因為雙重性
4.20 枚舉是按字符串值在底層對應的數字排序的,所以一般最好是按照需要的順序來定義枚舉。
4.21 枚舉值都被保存成了整數,只有在查詢時才能轉換為字符串,所以會有一定的開銷。
4.22 枚舉的字符串列表是固定的,添加或刪除時必須使用ALTER TABLE。
5 日期類型
5.1 MySQL存儲時間的最小精度為秒
5.2 Datetime時間類型存儲的范圍是1001年~9999年,精度為秒,占8個字節的長度。
5.3 Timestamp的存儲范圍是1970年~2038年,存的是時間戳,只占4個字節的長度。
5.4 Timestamp列會默認設置為Not null ,所以在插入數據時,若不給值就會默認為當前時間。
5.5 實現精度比秒更高的辦法:
1)使用Bigint存儲微秒級別的時間戳
2)用Double存儲秒之后的小數部分
個人更偏向于使用datetime,timestamp不能像datetime那樣可以使用函數,存儲時間也只能到2038年。
6 位數據類型
從技術上來說,位類型都是字符串類型
Bit(慎用)
MySQL將Bit當作字符串類型,而不是數字類型。如果檢索BIT(1)的值時,結果是一個包含二進制0或1的字符串,而不是ASCII碼的0或1。
Bit的最大長度是64
Set
如果需要保存許多true/false值,可用set數據類型
7 其它
select Inet_ATON(‘127.0.0.1’);——>2130706433
select Inet_ATON(‘127.1’); ——>2130706433
select Inet_NTOA(3520061480);——>209.207.224.40
總結
以上是生活随笔為你收集整理的优化MySQL数据类型——《深究MySQL》的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mybatis中 Integer 值为0
- 下一篇: 高性能的索引实现——《深究MySQL》