mysql set schema_Mysql数据库优化学习之一 Schema优化
引用
mysql> CREATE TABLE enum_test(
->
e ENUM('fish', 'apple', 'dog') NOT NULL
-> );
mysql> INSERT INTO enum_test(e) VALUES('fish'), ('dog'), ('apple');
mysql> SELECT e + 0 FROM enum_test;
+-------+
| e + 0 |
+-------+
|
1 |
|
3 |
|
2 |
+-------+
ENUM字段排序是按照內(nèi)部存儲的整數(shù)排的,你可以顯示的使用FIELD來指定排序的方式。
引用
mysql> SELECT e FROM enum_test ORDER BY FIELD(e, 'apple', 'dog', 'fish');
+-------+
| e
|
+-------+
| apple |
| dog
|
| fish |
+-------+
ENUM最大的缺點是字符串列表是固定大小的,添加和刪除一個字符串需要使用ALTER TABLE,所以如果你表示的字符串有可能在將來改變,那么使用ENUM并不是一個好的主意。
如果ENUM需要和char,varchar進(jìn)行join操作,那么會慢一些,這時候最好同一類型,
但是使用ENUM能夠比使用char,varchar節(jié)省不少空間的。
日期和時間類型:
MySQL有各種日期和時間的類型,比如YEAR,DATE,MySQL能存儲的最小時間粒度是秒,但是可以在微妙級別做臨時的運算。
DATETIME:
這個類型能夠保存更大范圍的值,從1001到9999,精度為1秒,他將日期和時間存儲為整數(shù)格式為YYYYMMDDHHMMSS,和時區(qū)無關(guān),使用了8個字節(jié)。
TIMESTAMP:
TIMESTAMP按照字面意思,存儲了從1970.1.1流失了多少秒,和Unix的timestamp一樣。
TIMESTAMP僅使用了4個自己,所以要比DATETIME小很多:從1970到2038. MySQL提供了
FROM_UNIXTIME()和UNIX_TIMESTAMP()函數(shù)來將Unix時間戳和日期轉(zhuǎn)換。
TIMESTAMP是和時區(qū)相關(guān)的。
時間戳有一些DATETIME沒有的功能,他沒在插入數(shù)據(jù)的時候,如果該列為空,則自動將當(dāng)前時間插入。當(dāng)更新一行數(shù)據(jù)時,這行數(shù)據(jù)的TIMESTAMP列默認(rèn)會跟新為當(dāng)前時間,除非顯式的指定值,TIMESTAMP列默認(rèn)是NOT NULL的。
一般來說你應(yīng)該使用TIMESTAMP,因為他比DATETIME占用更少的空間。有一些人喜歡存儲
Unix時間戳為一個整數(shù),但常常沒有給你帶來任何好處,因為這種格式不方便處理,我們并不推薦這么用。
Bit壓縮類型(Bit-packed Data Types)
MySQL提供了一些存儲類型,他每一個bit存儲一個值來的更緊湊的存儲數(shù)據(jù)方式。所有的
這些類型都是字符串類型,不管底層的存儲格式和操作:
BIT 在MySQL5.0之前,BIT是TINYINT的同義詞。但是在5.0之后,它是一個完全不同的類型,具有特殊的特性:你可以使用BIT列來存儲true/false值。BIT(1)定義了包含了單個比特,BIT(2)存儲了兩個bit,BIT字段的最大值是64bit。
BIT類型的行為在不同的存儲引擎中不同,MyISAM將這些列一起壓縮存儲,所以17個BIT列只需要17bit的存儲空間(沒有列是NULL的)。其他的存儲引擎比如Memory和InnoDB,使用足夠大的integer類型來存儲,所以使用BIT并沒有節(jié)省多少空間。
MySQL將BIT類型視為字符串類型而不是數(shù)字類型。如果使用BIT(1),查詢出來的是一個字符串,內(nèi)容是二進(jìn)制的0或者1,但不是ASCCII碼的‘0’,’1‘的值。
但是在數(shù)字的場景下使用,其值是字符串二進(jìn)制表示的值,比如b'00111001'為57.
這可能會比較讓人費解,所以我們建議謹(jǐn)慎的使用BIT,在大多數(shù)的應(yīng)用中,避免使用。
如果想存儲true/false中使用單個bit的存儲空間,那么另外的選擇是使用varchar(0),
這個列可以存儲NULL或者空字符串。
SET
如果你想存儲很多的true/false值,那么考慮將很多列組合成1列,使用SET數(shù)據(jù)類型,內(nèi)部表示為壓縮的bit集合。MySQL有函數(shù)FIND_IN_SET()和FIELD(),讓在查詢中使用
更容易。主要的缺點是,修改需要ALTER TABLE.
在整數(shù)列使用bit操作
另一種對于SET的選擇是使用整數(shù)作為壓縮的比特集合,比如你可以在TINYINT類型使用
8個bit,然后通過bit操作。這種方式相對于SET的最大有點是修改這個字段不需要ALTER TABLE。缺點是比較拿寫和理解,位操作,有人喜歡有人不喜歡,所以完全看你的口味了。
選擇主鍵:
選擇一個主鍵的正確類型是非常重要的。你經(jīng)常使用這些列來和其他的值比較,或者使用它來查找,在其他的表中作為外鍵。選擇主鍵不僅僅藥考慮存儲的類型,還要考慮比較和計算的性能。比如MySQL存儲ENUM和SET類型的內(nèi)部形式是整數(shù),但是在字符串的環(huán)境下會轉(zhuǎn)化為字符串。
一旦選擇好一個類型,要確保所有關(guān)聯(lián)的表對應(yīng)的外鍵具有相同的類型。類型要精確的匹配比較好,除了UNSIGNED。混用不同的類型可能導(dǎo)致性能問題,并且隱式的類型轉(zhuǎn)換可能會帶來錯誤。
選擇能夠包含數(shù)據(jù)區(qū)間的最小的類型,比如你想用state_id字段來存儲美國的州,那么TINYINT已經(jīng)足夠。
整數(shù)類型:
通常是最佳的主鍵類型的選擇,因為它速度快并且可以自增。
ENUM和SET:
通常是一個比較糟糕的選擇,他們比較適合作為狀態(tài),類型的值。
String類型:
盡可能避免使用字符串類型的主鍵,因為占用較多的空間并且比整數(shù)慢。使用MyISAM的表更應(yīng)該特別謹(jǐn)慎使用字符串類型的主鍵,因為他會默認(rèn)壓縮字符串索引,這會導(dǎo)致查詢非常慢。
使用packed索引大約要慢六倍。
使用完全隨機(jī)的字符串,比如MD5(),SHA1(),UUID(),要特別小心,每一個新生成的值都會
在一個很大空間的一個隨機(jī)的值,這將會降低插入和部分查詢語句。
INSERT慢的原因是插入的值在索引的隨機(jī)位置,這會導(dǎo)致頁的分裂或者磁盤的隨機(jī)訪問,對于聚集存儲引擎會引起聚集索引碎片。
SELECT慢的原因邏輯相鄰的行將會在磁盤和內(nèi)存分散。
隨機(jī)的值也會導(dǎo)致所有類型查詢的緩存表現(xiàn)很差。
特殊類型數(shù)據(jù):
比如很多人使用VARCHAR(15)來表示IP,其實IP是一個無符號的32為整數(shù),所以存儲IP地址為整數(shù)是一個比較好的方法。MySQL提供了INET_ATON()和INET_NTOA函數(shù)來轉(zhuǎn)換這兩種表示。
參考《高性能MySQL》
分享到:
2011-05-12 23:32
瀏覽 3789
分類:數(shù)據(jù)庫
評論
總結(jié)
以上是生活随笔為你收集整理的mysql set schema_Mysql数据库优化学习之一 Schema优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 交强险和商业险不是一家可以吗
- 下一篇: linux cmake编译源码,linu