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