·????????BLOB/TEXT
在實(shí)際的應(yīng)用程序中往往需要存儲(chǔ)兩種體積較大的數(shù)據(jù),一種是較大的Binary數(shù)據(jù),e.g. 一張10M的圖片,另外一種是 較大的文本 e.g.一篇幾萬(wàn)字的文章。在Oracle中有BOLB和CLOB來(lái)應(yīng)對(duì)這兩種數(shù)據(jù),而在MySQL中對(duì)應(yīng)的是BLOB以及TEXT.
鑒于這兩種數(shù)據(jù)類(lèi)型的特殊性,在MySQL中對(duì)BLOB以及TEXT的存儲(chǔ)和操作做了特殊的處理:
????????? 1) BLOB/TEXT 的值往往是作為對(duì)象來(lái)處理,這些對(duì)象有自己的ID,以及獨(dú)立的存儲(chǔ)空間
????????? 2) BLOB/TEXT的值被用來(lái)排序的時(shí)候,只有前N個(gè)字節(jié)會(huì)被使用,N 對(duì)應(yīng)的是數(shù)據(jù)庫(kù)中的一個(gè)常量值 (
max_sort_length
), 如果你想指定更多的字節(jié)被用來(lái)排序,那么你可以增加
max_sort_length
的值或者是使用
ORDER BY SUBSTRING(column, length)
函數(shù)來(lái)處理
????????? 3) 當(dāng)BLOB/TEXT 被用作索引或者排序的時(shí)候,不能使用整個(gè)字段的值.
在萬(wàn)不得已的情況下要避免把BOLB/TEXT用作索引或是排序
因?yàn)镸ySQL 的Memory 引擎不支持BLOB 和TEXT 類(lèi)型,所以,如果查詢(xún)的過(guò)程中涉及到BLOB /TEXT,則需要使用MyISAM 磁盤(pán)臨時(shí)表,即使只有幾行數(shù)據(jù)也是如此(在最新的Percona Server 的Memory 引擎支持BLOB 和TEXT 類(lèi)型)。
Memory引擎頻繁的訪問(wèn)磁盤(pán)臨時(shí)表會(huì)產(chǎn)生嚴(yán)重的性能開(kāi)銷(xiāo),最好的解決方案是盡量避免使用BLOB 和TEXT 類(lèi)型。如果實(shí)在無(wú)法避免,有一個(gè)技巧是在所有用到BLOB 字段的地方都使用SUBSTRING(column, length) 將列值轉(zhuǎn)換為字符串(在ORDER BY 子句中也適用),這樣就可以使用內(nèi)存臨時(shí)表了。但是要確保截取的子字符串足夠短,不會(huì)使臨時(shí)表的大小超過(guò)max_heap_table_size 或tmp_table_size,超過(guò)以后MySQL 會(huì)將內(nèi)存臨時(shí)表轉(zhuǎn)換為MyISAM 磁盤(pán)臨時(shí)表。
?
最壞情況下的長(zhǎng)度分配對(duì)于排序的時(shí)候也是一樣的,所以這一招對(duì)于內(nèi)存中創(chuàng)建大臨時(shí)表和文件排序,以及在磁盤(pán)上創(chuàng)建大臨時(shí)表和文件排序這兩種情況都很有幫助。例如,假設(shè)有一個(gè)1 000 萬(wàn)行的表,占用幾個(gè)GB 的磁盤(pán)空間。其中有一個(gè)utf8字符集的VARCHAR(1000) 列。每個(gè)字符最多使用3 個(gè)字節(jié),最壞情況下需要3 000字節(jié)的空間。如果在ORDER BY 中用到這個(gè)列,并且查詢(xún)掃描整個(gè)表,為了排序就需要超過(guò)30GB 的臨時(shí)表
·?????? DATETIME/TIMESTAMP
在MySQL中包含兩種時(shí)間格式 DATETIME,TIMESTAMP, 通常在使用的過(guò)程中這兩種類(lèi)型區(qū)別不是很大,但是在細(xì)節(jié)上還是存在差別
? |
DATETIME |
TIMESTAMP |
占用空間 |
8Bytes |
4Bytes |
可表示區(qū)間(年) |
1001-9999 |
1970-2038 |
是否與時(shí)區(qū)有關(guān) |
否 |
是 |
存儲(chǔ)內(nèi)容 |
日期和時(shí)間封裝到格式為YYYYMMDDHHMMSS 的整數(shù)中 |
保存了從1970 年1 月1 日午夜(格林尼治標(biāo)準(zhǔn)時(shí)間)以來(lái)的秒數(shù),它和UNIX 時(shí)間戳相同 |
顯示方式是否與時(shí)區(qū)有關(guān) |
否(ANSI 標(biāo)準(zhǔn)定義的日期和時(shí)間表示方法) |
是 |
特殊屬性 |
? |
(1)TIMESTAMP 列默認(rèn)為NOT NULL,默認(rèn)值為當(dāng)前時(shí)間 |
因?yàn)門(mén)MESSTAMP會(huì)占用更小的存儲(chǔ)空間,所以可以使用它作為默認(rèn)的時(shí)間格式
·?????? ENUM
這種類(lèi)型的字段主要是通過(guò)枚舉的方式來(lái)保存列的值,因?yàn)樵谑褂玫倪^(guò)程中會(huì)涉及到枚舉位置與實(shí)際值的轉(zhuǎn)換,所以對(duì)于整體的性能可能會(huì)有
一定的影響,而且枚舉的值是存儲(chǔ)在
.frm(數(shù)據(jù)表結(jié)構(gòu)定義文件)
中,所以當(dāng)建立完ENUM的列后,如果你想對(duì)EMUM的內(nèi)容進(jìn)行更新,也就相當(dāng)于做了表結(jié)構(gòu)的更新。
下面是個(gè)簡(jiǎn)單建立ENUM列的例子:
mysql> CREATE TABLEenum_test(
->? e ENUM('fish', 'apple', 'dog') NOT NULL
-> );
mysql> INSERT INTOenum_test(e) VALUES('fish'), ('dog'), ('apple');
·????????BIT
如果需要讓你設(shè)計(jì)一個(gè)表示布爾值的字段要求占用的空間最少,你會(huì)如何去設(shè)計(jì)?用INT,還是用CHAR(1)?相比INT以及CHAR(1)而言BIT(1)或許是個(gè)更好的選擇,因?yàn)樗加玫目臻g只是一個(gè)BIT。它可以通過(guò)BIT(N)的方式來(lái)表達(dá)多個(gè)BIT的值,這種方式最大支持到BIT(64)。
在MySQL5.0之前的版本中,BIT被認(rèn)為是和TINYINT等同的,在新的版本中被作為兩種完全不同的類(lèi)型來(lái)對(duì)待。
當(dāng)你把一個(gè)BIT字段從數(shù)據(jù)庫(kù)中檢索出來(lái)顯示在控制臺(tái)上時(shí),值會(huì)被顯示成ASCII編碼,當(dāng)字段的值出在一個(gè)數(shù)字運(yùn)算的上下文時(shí),它會(huì)被當(dāng)成是BIT的十進(jìn)制的值,下面的一個(gè)例子可以很清楚的說(shuō)明這兩種情況
mysql>CREATE TABLE bittest(a bit(8));
mysql> INSERT INTObittest VALUES(b'00111001');
mysql> SELECT a, a+ 0 FROM bittest;
+------+-------+
| a | a + 0 |
+------+-------+
| 9 | 57 |
+------+-------+
上面的這個(gè)例子或許會(huì)讓你感到困惑,很有可能讓你不再想使用這種機(jī)制來(lái)存儲(chǔ)單個(gè)的位,作為一種替代方案可以把相關(guān)字段設(shè)置成
CHAR(0)
,
NULL
用來(lái)表示False,
””(Empty String)
表示True
更多內(nèi)容請(qǐng)參考 ?
高性能MySql進(jìn)化論(一):數(shù)據(jù)類(lèi)型的優(yōu)化_上
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
