日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

MySQL數(shù)據(jù)庫(kù)技術(shù)(09)

 Ralf_Jones 2006-07-19
破釜沉舟 http://www.


文章類(lèi)別:MySQL  發(fā)表日期:2005-09-23      閱讀次數(shù): 93

 

2.3 選擇列的類(lèi)型
    上一節(jié)描述了各種可供選擇的MySQL 的列類(lèi)型及其屬性,以及它們可存儲(chǔ)的各種值,所占用的存儲(chǔ)空間等等。但是在實(shí)際創(chuàng)建一個(gè)表時(shí)怎樣決定用哪些類(lèi)型呢?本節(jié)討論在做出決定前應(yīng)考慮的各種因素。最“常用”的列類(lèi)型是串類(lèi)型。可將任何數(shù)據(jù)存儲(chǔ)為串,因?yàn)閿?shù)和日期都可以串的形式表示。但是為什么不將所有列都定義為串從而結(jié)束這里的討論呢?讓我們來(lái)看一個(gè)簡(jiǎn)單的例子。假定有一些看起來(lái)像數(shù)的值。可將它們表示為串,但應(yīng)該這樣做嗎?這樣做會(huì)發(fā)生什么事?
    有一樁事不可避免,那就是可能要使用更多的空間,因?yàn)檩^串來(lái)說(shuō),數(shù)的存儲(chǔ)更為有效。我們可能已經(jīng)注意到,由于數(shù)和串處理方式的不同,查詢(xún)結(jié)果也有所不同。例如,數(shù)的排序與串的排序就有所不同。數(shù)2 小于數(shù)11,但串“2”按字典順序大于“ 11”??捎萌缦聰?shù)值內(nèi)容的列來(lái)搞清這個(gè)問(wèn)題:

    將零加到該列強(qiáng)制得出一個(gè)數(shù)值,但是這樣合理嗎?一般可能不合理。將該列作為數(shù)而不是串具有幾個(gè)重要的含義。它對(duì)每個(gè)列值實(shí)施串到數(shù)的轉(zhuǎn)換,這是低效的。而且將該列的值轉(zhuǎn)換為計(jì)算結(jié)果妨礙MySQL 使用該列上的索引,降低了以后的查詢(xún)速度。如果這些值一開(kāi)始就是作為數(shù)值存儲(chǔ)的,那么這些性能上的降低都不會(huì)出現(xiàn)。采用一種表示而不用另一種的簡(jiǎn)單選擇實(shí)際上并不簡(jiǎn)單,它在存儲(chǔ)需求、查詢(xún)效率以及處理性能等方面都會(huì)產(chǎn)生重要的影響。
    前面的例子說(shuō)明,在選擇列類(lèi)型時(shí),有以下幾個(gè)問(wèn)題需要考慮:
    ■ 列中存儲(chǔ)何種類(lèi)型的值?這是一個(gè)顯而易見(jiàn)的問(wèn)題,但必須確定。可將任何類(lèi)型的值表示為串,尤其當(dāng)對(duì)數(shù)值使用更為合適的類(lèi)型可能得到更好的性能時(shí)(日期和時(shí)間值也是這樣)。可見(jiàn),對(duì)要處理的值的類(lèi)型進(jìn)行評(píng)估不一定是件微不足道的事,特別在數(shù)據(jù)是別人的數(shù)據(jù)時(shí)更是如此。如果正在為其他人建立一個(gè)表,搞清列中要存儲(chǔ)的值的類(lèi)型極為重要,必須提足夠多的問(wèn)題以便得到作出決定的充足的信息。
    ■ 列值有特定的取值范圍嗎?如果它們是整數(shù),它們總是非負(fù)值嗎?如果這樣,可采用UNSIGNED 類(lèi)型。如果它們是串,總能從定長(zhǎng)值集中選出它們嗎?如果這樣, E N U M或SET 是很合適的類(lèi)型。在類(lèi)型的取值范圍與所用的存儲(chǔ)量之間存在折衷。需有一個(gè)多“大”的類(lèi)型?對(duì)于數(shù),如果其取值范圍有限,可以選擇較小的類(lèi)型,對(duì)取值范圍幾乎無(wú)限的數(shù),應(yīng)該選擇較大的類(lèi)型。對(duì)于串,可以使它們短也可以使它們長(zhǎng),但如果希望存儲(chǔ)的值只含不到10 個(gè)字符,就不應(yīng)該選用C H A R ( 2 5 5 )。
    ■ 性能與效率問(wèn)題是什么?有些類(lèi)型比另外一些類(lèi)型的處理效率高。數(shù)值運(yùn)算一般比串的運(yùn)算快。短串比長(zhǎng)串運(yùn)行更快,而且磁盤(pán)消耗更小。定長(zhǎng)類(lèi)型比可變長(zhǎng)類(lèi)型的性能更好。
    ■ 希望對(duì)值進(jìn)行什么樣的比較?對(duì)于串,其比較可以是區(qū)分大小寫(xiě)的,也可以不區(qū)分大小寫(xiě)。其選擇也會(huì)影響排序,因?yàn)樗腔诒容^的。
    ■ 計(jì)劃對(duì)列進(jìn)行索引嗎?如果計(jì)劃對(duì)列進(jìn)行索引,那么將會(huì)影響您對(duì)列類(lèi)型的選擇,因?yàn)橛械腗ySQL 版本不允許對(duì)某些類(lèi)型進(jìn)行索引,例如不能對(duì)BLOB 和TEXT 類(lèi)型進(jìn)行索引。而且有的MySQL 版本要求定義索引列為NOT NULL 的,這使您不能使用NULL 值。
    現(xiàn)在讓我們來(lái)更詳細(xì)地考慮這些問(wèn)題。這里要指出的是:在創(chuàng)建表時(shí),希望作出盡可能好的列類(lèi)型選擇,但如果所作的選擇其實(shí)際并不是最佳的,這也不會(huì)帶來(lái)多大的問(wèn)題??捎肁 LTER TABLE 將原來(lái)選擇的類(lèi)型轉(zhuǎn)換為更好的類(lèi)型。在發(fā)現(xiàn)數(shù)據(jù)所含的值比原設(shè)想的大時(shí),可像將SMALLINT 更換成MEDIUMINT 那樣簡(jiǎn)單地對(duì)類(lèi)型進(jìn)行更換。有時(shí)這種更換也可能很復(fù)雜,例如將CHAR 類(lèi)型更換成具有特定值集的ENUM 類(lèi)型。在MySQL 3.23 及以后的版本中,可使用PROCEDURE ANALYSE( ) 來(lái)獲得表列的信息,諸如最小值和最大值以及推薦的覆蓋列中值的取值范圍的最佳類(lèi)型。這有助于確定使用更小的類(lèi)型,從而改進(jìn)涉及該表的查詢(xún)的性能,并減少存儲(chǔ)該表所需的空間量。
    2.3.1 列中存儲(chǔ)何種類(lèi)型的值
    在決定列的類(lèi)型時(shí),首先應(yīng)該考慮該列的值類(lèi)型,因?yàn)檫@對(duì)于所選擇的類(lèi)型來(lái)說(shuō)具有最為明顯的意義。通常,在數(shù)值列中存儲(chǔ)數(shù),在串列中存儲(chǔ)串,在日期和時(shí)間列中存儲(chǔ)日期和時(shí)間。如果數(shù)值有小數(shù)部分,那么應(yīng)該用浮點(diǎn)列類(lèi)型而不是整數(shù)類(lèi)型,如此等等。有時(shí)也存
在例外,不可一概而論。主要是為了有意義地選擇類(lèi)型,應(yīng)該理解所用數(shù)據(jù)的特性。如果您打算存儲(chǔ)自己的數(shù)據(jù),大概對(duì)如何存儲(chǔ)它們會(huì)有自己很好的想法。但是,如果其他人請(qǐng)您為
    他們建一個(gè)表,決定列類(lèi)型有時(shí)會(huì)很困難。這不像處理自己的數(shù)據(jù)那么容易。應(yīng)該充分地提問(wèn),搞清表實(shí)際應(yīng)該包含何種類(lèi)型的值。
如果有人告訴您,某列需要記錄“降雨量”。那是一個(gè)數(shù)嗎?或者它“主要”是一個(gè)數(shù)值,即,一般是但不總是編碼成一個(gè)數(shù)嗎?例如,在看電視新聞時(shí),氣象預(yù)報(bào)一般包括降雨量。有時(shí)是一個(gè)數(shù)(如“ 0 . 2 5”英寸的雨量),但是有時(shí)是“微量( t r a c e )”降雨,意思是“雨根本就不大”。這對(duì)氣象預(yù)報(bào)很合適,但在數(shù)據(jù)庫(kù)中怎樣存儲(chǔ)?有可能需要將“微量”量化為一個(gè)數(shù),以便能用數(shù)值列類(lèi)型來(lái)記錄降雨量,或許需要使用串,以便可以記錄“微量”這個(gè)詞?;蛘呖梢蕴岢瞿撤N更為復(fù)雜的安排,使用一個(gè)數(shù)值列和一個(gè)串列,如果填充一個(gè)列就讓另一個(gè)列為N U L L。很明顯,可能的話(huà),應(yīng)該避免最后這種選擇;最后這種選擇使表難于理解,使查詢(xún)更為困難。我們一般盡量以數(shù)值形式存儲(chǔ)所有的行,而且只為了顯示的需要才對(duì)它們進(jìn)行轉(zhuǎn)換。例如,如果小于0.01 英寸的非零降雨量被視為微量,那么可以如下選擇列值:

    對(duì)于金錢(qián)的計(jì)算,需要處理元和分部分。這似乎像浮點(diǎn)值,但F L O AT 和DOUBLE 容易出現(xiàn)舍入錯(cuò)誤,除了只需要大致精確的記錄外,這些類(lèi)型可能不適合。因?yàn)槿藗儗?duì)自己的錢(qián)都是很敏感的,最好是用一種能提供完善的精確性的類(lèi)型,例如:
    ■ 將錢(qián)表示為DECIMAL(M, 2) 類(lèi)型,選擇M 為適合于所需取值范圍的最大寬度。這給出具有兩位小數(shù)精度的浮點(diǎn)值。DECIMAL 的優(yōu)點(diǎn)是將值表示為一個(gè)串,而且不容易出現(xiàn)舍入錯(cuò)誤。不利之處是串運(yùn)算比內(nèi)部存儲(chǔ)為數(shù)的值上的運(yùn)算效率差。
    ■ 可在內(nèi)部用整數(shù)類(lèi)型來(lái)表示所有的錢(qián)值。其優(yōu)點(diǎn)是內(nèi)部用整數(shù)來(lái)計(jì)算,這樣會(huì)非???。不利之處是在輸入或輸出時(shí)需要利用乘或除100 對(duì)值進(jìn)行轉(zhuǎn)換。有些數(shù)據(jù)顯然是數(shù)值的,但必須決定是使用浮點(diǎn)類(lèi)型還是使用整數(shù)類(lèi)型。應(yīng)該搞清楚所用的單位是什么以及需要什么樣的精度。整個(gè)單元的精度都?jí)騿??或者需要表示小?shù)的單元嗎?這將有助于您在整數(shù)列和浮點(diǎn)數(shù)列之間進(jìn)行區(qū)分。例如,如果您正表示權(quán)重,那么如果記錄的值為英磅,可以使用一個(gè)整形列。如果希望記錄小數(shù)部分,就應(yīng)該使用浮點(diǎn)列。在有的情況下,甚至?xí)褂枚鄠€(gè)字段,例如:如果希望根據(jù)磅和盎司記錄權(quán)重,則可以使用多個(gè)列。
    高度(h e i g h t)是另外一種數(shù)值類(lèi)型,有如下幾種表示方法:
    ■ 諸如“6 英尺2 英寸”可表示為“ 6 - 2”這樣一個(gè)串。這種形式具有容易察看和理解的優(yōu)點(diǎn)(當(dāng)然比“ 74 英寸更好理解”),但是這種值很難用于數(shù)學(xué)運(yùn)算,如求和或取平均值。
    ■ 一個(gè)數(shù)值字段表示英尺,另一個(gè)數(shù)值字段表示英寸。這樣的表示進(jìn)行數(shù)值運(yùn)算相對(duì)容易,但兩個(gè)字段比一個(gè)字段難于使用。
    ■ 只用一個(gè)表示英寸的數(shù)值段。這是數(shù)據(jù)庫(kù)最容易處理的方式,但是這種方式意義最不明確。不過(guò)要記住,不一定要用與您慣常使用的那種格式來(lái)表示值??梢杂肕 y S Q L的函數(shù)將值轉(zhuǎn)換為看上去意義明顯的值。因此,最后這種表示方法可能是表示高度的最好方法。
    如果需要存儲(chǔ)日期信息,需要包括時(shí)間嗎?即,它們永遠(yuǎn)都需要包括時(shí)間嗎? MySQL 不提供具有可選時(shí)間部分的日期類(lèi)型: D ATE 可不包含時(shí)間,而D ATETIME 必須包含時(shí)間。如果時(shí)間確實(shí)是可選的,那么可用一個(gè)D ATE 列記錄日期,一個(gè)TIME 列記錄時(shí)間。允許TIME 列為NULL 并解釋為“無(wú)時(shí)間”:

    在用基于日期信息的主-細(xì)目關(guān)系連接兩個(gè)表時(shí),決定是否需要時(shí)間值特別重要。假如您正在進(jìn)行一項(xiàng)研究,包括一些對(duì)進(jìn)入您的辦公室的人進(jìn)行測(cè)試的題目。在一個(gè)標(biāo)準(zhǔn)的初步測(cè)試集之后,您可能會(huì)在同一天進(jìn)行幾個(gè)額外的測(cè)試,測(cè)試的選擇視初步測(cè)試結(jié)果而定。您可能會(huì)利用一個(gè)主-細(xì)目關(guān)系來(lái)表示這些信息,其中題目的標(biāo)識(shí)信息和標(biāo)準(zhǔn)的初步測(cè)試存儲(chǔ)在一個(gè)主記錄中,而其他測(cè)試保存為輔助細(xì)目表的行。然后基于題目ID 與進(jìn)行測(cè)試的日期將這兩個(gè)表連接到一起。
    在這種情況下必須回答的問(wèn)題是,是否可以只用日期,或者是否需要既使用日期又使用時(shí)間。這個(gè)問(wèn)題依賴(lài)于一個(gè)題目是否可以在同一天投入測(cè)試過(guò)程不止一次。如果是這樣,那么應(yīng)該記錄時(shí)間(比方說(shuō),記錄測(cè)試過(guò)程開(kāi)始的時(shí)間),或者用D ATETIME 列,或者分別用
DATE 和TIME 列(兩者都必須填寫(xiě))。如果一個(gè)題目一天測(cè)試了兩次,沒(méi)有時(shí)間值就不能將該題目的細(xì)目記錄與適當(dāng)?shù)闹饔涗涍M(jìn)行關(guān)聯(lián)。
我曾經(jīng)聽(tīng)過(guò)有人聲稱(chēng)“我不需要時(shí)間;我從不在同一天把一道題測(cè)試兩次”。有時(shí)他們是對(duì)的,但是我也看到過(guò)這些人后來(lái)在錄入同一天測(cè)試多次的題目的數(shù)據(jù)后,反過(guò)來(lái)考慮怎樣防止細(xì)目記錄與錯(cuò)誤的主記錄相混。很抱歉,這時(shí)已經(jīng)太遲了!有時(shí)可以在表中增加TIME 列來(lái)處理這個(gè)問(wèn)題,不幸的是,除非有某些獨(dú)立的數(shù)據(jù)源,如原書(shū)面記錄,否則很難整理現(xiàn)有記錄。此外,沒(méi)辦法消除細(xì)目記錄的歧義,以便將它們關(guān)聯(lián)到合適的主記錄上。即使有獨(dú)立的信息源,這樣做也是非常亂的,很可能使已經(jīng)編寫(xiě)來(lái)利用表的應(yīng)用程序出問(wèn)題。最好是向表的擁有者說(shuō)明問(wèn)題并保證在創(chuàng)建他們的表之前進(jìn)行很好的描述。
    有時(shí)具有一些不完整的數(shù)據(jù),這會(huì)干擾列類(lèi)型的選擇。如果進(jìn)行家譜研究,需要記錄出生日期和死亡日期,有時(shí)會(huì)發(fā)現(xiàn)所能搜集到的數(shù)據(jù)中只是某人出生或死亡的年份,但沒(méi)有確切的日期。如果使用D ATE 列,除非有完整的日期值,否則不能輸入日期。如果希望能夠記
錄所具有的任何信息,即使不完整也保存,那么可能必須保存獨(dú)立的年、月、日字段。這樣就可以輸入所具有的日期成員并將沒(méi)有的部分設(shè)為N U L L。在MySQL 3.23 及以后的版本中,還允許D ATE 的日為0 或者月和日部分為0。這樣“模糊”的日期可用來(lái)表示不完整的日期值。
    2.3.2 列值有特定的取值范圍嗎
    如果已經(jīng)決定從通用類(lèi)別上選擇一種列類(lèi)型,那么考慮想要表示的值的取值范圍會(huì)有助于將您的選擇縮減到該類(lèi)別中特定的類(lèi)型上。假如希望存儲(chǔ)整數(shù)值。這些整數(shù)值的取值范圍為0 到1 0 0 0,那么可以使用從SMALLINT 到BIGINT 的所有類(lèi)型。如果這些整數(shù)值的取值
范圍最多為2 000 000,則不能使用S M A L L I N T,其選擇范圍從MEDIUMINT 到B I G I N T。需要從這個(gè)可能的選擇范圍中選取一種類(lèi)型。當(dāng)然,可以簡(jiǎn)單地為想要存儲(chǔ)的值選擇最大的類(lèi)型(如上述例子中選擇B I G I N T)。但是,一般應(yīng)該為所要存儲(chǔ)的值選擇足以存儲(chǔ)它的最小的類(lèi)型。這樣做,可以最小化表占用的存儲(chǔ)量,得到最好的性能,因?yàn)橥ǔ]^小列的處理比較大列的快。如果不知道所要表示的值的取值范圍,那么必須進(jìn)行猜測(cè)或使用BIGINT 以應(yīng)付最壞的情況。(請(qǐng)注意,如果進(jìn)行猜測(cè)時(shí)使用了一個(gè)太小的類(lèi)型,工作不會(huì)白做;以后可以利用A LTER TABLE 來(lái)將此列改為更大一些的類(lèi)型。)
    在第1章中,我們?yōu)閷W(xué)分保存方案創(chuàng)建了一個(gè)score 表,它有一個(gè)記錄測(cè)驗(yàn)和測(cè)試學(xué)分的score 列。為了討論簡(jiǎn)單起見(jiàn),創(chuàng)建該表時(shí)使用了INT 類(lèi)型,但現(xiàn)在可以看出,如果學(xué)分在0到100 的取值范圍內(nèi),更好的選擇應(yīng)該是TINYINT UNSIGNED,因?yàn)樗玫拇鎯?chǔ)空間較小。數(shù)據(jù)的取值范圍還影響列類(lèi)型的屬性。如果該數(shù)據(jù)從不為負(fù),可使用UNSIGNED 屬性;否則就不能用它。
    串類(lèi)型沒(méi)有數(shù)值列那樣的“取值范圍”,但它們有長(zhǎng)度,需要知道該串可使用的列最大長(zhǎng)度。如果串短于2 5 6個(gè)字符,可使用C H A R、VA R C H A R、TINYTEXT 或TINYBLOB 等類(lèi)型。如果想要更長(zhǎng)的串,可使用TEXT 或BLOB 類(lèi)型,而CHAR 和VARCHAR 不再是
選項(xiàng)。對(duì)于用來(lái)表示某個(gè)固定值集合的串列,可以考慮使用ENUM 或SET 列類(lèi)型。它們可能是很好的選項(xiàng),因?yàn)樗鼈冊(cè)趦?nèi)部是用數(shù)來(lái)表示的。這兩個(gè)類(lèi)型上的運(yùn)算是數(shù)值化的,因此,比其他的串類(lèi)型效率更高。它們還比其他串類(lèi)型緊湊、節(jié)省空間。在描述必須處理的值的范圍時(shí),最好的術(shù)語(yǔ)是“總是”和“決不”(如“總是小于1 0 0 0”或“決不為負(fù)”),因?yàn)樗鼈兡芨鼫?zhǔn)確地約束列類(lèi)型的選擇。但在未確證之前,要慎用這兩個(gè)術(shù)語(yǔ)。特別是與其他人談他們的數(shù)據(jù),而他們開(kāi)始亂用這兩個(gè)術(shù)語(yǔ)時(shí)要注意。在有人說(shuō)“總是”或“決不”時(shí),一定要搞清他們說(shuō)的確實(shí)是這個(gè)含義。有時(shí)人們說(shuō)自己的數(shù)據(jù)總是有某種特定的性質(zhì),而其真正的含義是“幾乎總是”。
    例如,假如您為某些人設(shè)計(jì)一個(gè)表,而他們告訴您,“我們的測(cè)試學(xué)分總是0 到1 0 0”。根據(jù)這個(gè)描述,您選擇了TINYINT 類(lèi)型并使它為UNSIGNED 的,因?yàn)橹悼偸欠秦?fù)的。然而,您發(fā)現(xiàn)編碼錄入數(shù)據(jù)庫(kù)的人有時(shí)用- 1 來(lái)表示“學(xué)生因病缺席”。呀,他們沒(méi)告訴您這事??赡芸梢杂肗ULL 來(lái)表示-1,但如果不能,必須記錄- 1,這樣就不能用UNSIGNED 列了(只好用A LTER TABLE 來(lái)補(bǔ)救!)。有時(shí)關(guān)于這些情形的討論可通過(guò)提一些簡(jiǎn)單的問(wèn)題來(lái)簡(jiǎn)化,如問(wèn):曾經(jīng)有過(guò)例外嗎?如果曾經(jīng)有過(guò)例外情況,即使是只有一次,也必須考慮。您會(huì)發(fā)現(xiàn),和您討論數(shù)據(jù)庫(kù)設(shè)計(jì)的人總是認(rèn)為,如果例外不經(jīng)常發(fā)生,那么就沒(méi)什么關(guān)系。然而在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),就不能這樣想了。需要提的問(wèn)題并不是例外出現(xiàn)有多頻繁,而是有沒(méi)有例外?如果有,必須考慮進(jìn)去。
    2.3.3 性能與效率問(wèn)題
    列類(lèi)型的選擇會(huì)在幾個(gè)方面影響查詢(xún)性能。如果記住下幾節(jié)討論的一般準(zhǔn)則,將能夠選出有助于MySQL 有效處理表的列類(lèi)型。
    1. 數(shù)值與串的運(yùn)算
    數(shù)值運(yùn)算一般比串運(yùn)算更快。例如比較運(yùn)算,可在單一運(yùn)算中對(duì)數(shù)進(jìn)行比較。而串運(yùn)算涉及幾個(gè)逐字節(jié)的比較,如果串更長(zhǎng)的話(huà),這種比較還要多。如果串列的值數(shù)目有限,應(yīng)該利用ENUM 或SET 類(lèi)型來(lái)獲得數(shù)值運(yùn)算的優(yōu)越性。這兩種類(lèi)型在內(nèi)部是用數(shù)表示的,可更為有效地進(jìn)行處理。例如替換串的表示。有時(shí)可用數(shù)來(lái)表示串值以改進(jìn)其性能。例如,為了用點(diǎn)分四位數(shù)(d o t t e d - q u a d)表示法來(lái)表示IP 號(hào),如1 9 2 . 1 6 8 . 0 . 4,可以使用串。但是也可以通過(guò)用四字節(jié)的UNSIGNED 類(lèi)型的每個(gè)字節(jié)存儲(chǔ)四位數(shù)的每個(gè)部分,將IP 號(hào)轉(zhuǎn)換為整數(shù)形式。這即可以節(jié)省空間又可加快查找速度。但另一方面,將IP 號(hào)表示為INT 值會(huì)使諸如查找某個(gè)子網(wǎng)的號(hào)碼這樣的模式匹配難于完成。因此,不能只考慮空間問(wèn)題;必須根據(jù)利用這些值做什么來(lái)決定哪種表示更適合。
    2. 更小的類(lèi)型與更大的類(lèi)型
    更小的類(lèi)型比更大的類(lèi)型處理要快得多。首先,它們占用的空間較小,且涉及的磁盤(pán)活動(dòng)開(kāi)銷(xiāo)也少。對(duì)于串,其處理時(shí)間與串長(zhǎng)度直接相關(guān)。一般情況下,較小的表處理更快,因?yàn)椴樵?xún)處理需要的磁盤(pán)I/O 少。對(duì)于定長(zhǎng)類(lèi)型的列,應(yīng)該選擇最小的類(lèi)型,只要能存儲(chǔ)所需范圍的值即可。例如,如果MEDIUMINT 夠用,就不要選擇B I G I N T。如果只需要F L O AT 精度,就不應(yīng)該選擇D O U B L E。對(duì)于可變長(zhǎng)類(lèi)型,也仍然能夠節(jié)省空間。一個(gè)BLOB 類(lèi)型的值用2 字節(jié)記錄值的長(zhǎng)度,而一個(gè)LONGBLOB 則用4 字節(jié)記錄其值的長(zhǎng)度。如果存儲(chǔ)的值長(zhǎng)度永遠(yuǎn)不會(huì)超過(guò)6 4 K B,使用BLOB 將使每個(gè)值節(jié)省2 字節(jié)(當(dāng)然,對(duì)于TEXT 類(lèi)型也可以做類(lèi)似的考慮)。
    3. 定長(zhǎng)與可變長(zhǎng)類(lèi)型
    定長(zhǎng)類(lèi)型一般比可變長(zhǎng)類(lèi)型處理得更快:
    ■ 對(duì)于可變長(zhǎng)列,由于記錄大小不同,在其上進(jìn)行許多刪除和更改將會(huì)使表中的碎片更多。需要定期運(yùn)行OPTIMIZE TABLE 以保持性能。而定長(zhǎng)列就沒(méi)有這個(gè)問(wèn)題。
    ■ 在出現(xiàn)表崩潰時(shí),定長(zhǎng)列的表易于重新構(gòu)造,因?yàn)槊總€(gè)記錄的開(kāi)始位置是確定的??勺冮L(zhǎng)列就沒(méi)有這種便利。這不是一個(gè)與查詢(xún)處理有關(guān)的性能問(wèn)題,但它必定能加快表的修復(fù)過(guò)程。如果表中有可變長(zhǎng)的列,將它們轉(zhuǎn)換為定長(zhǎng)列能夠改進(jìn)性能,因?yàn)槎ㄩL(zhǎng)記錄易于處理。在試圖這樣做之前,應(yīng)該考慮下列問(wèn)題:
    ■ 使用定長(zhǎng)列涉及某種折衷。它們更快,但占用的空間更多。CHAR(n) 類(lèi)型列的每個(gè)值總要占用n 個(gè)字節(jié)(即使空串也是如此),因?yàn)樵诒碇写鎯?chǔ)時(shí),值的長(zhǎng)度不夠?qū)⒃谟疫呇a(bǔ)空格。而VARCHAR(N) 類(lèi)型的列所占空間較少,因?yàn)橹唤o它們分配存儲(chǔ)每個(gè)值所需要的空間,每個(gè)值再加一個(gè)字節(jié)用于記錄其長(zhǎng)度。因此,如果在CHAR 和VARCHAR列之間進(jìn)行選擇,需要對(duì)時(shí)間與空間作出折衷。如果速度是主要關(guān)心的因素,則利用CHAR 列來(lái)取得定長(zhǎng)列的性能優(yōu)勢(shì)。如果空間是關(guān)鍵,應(yīng)該使用VARCHAR 列。
    ■ 不能只轉(zhuǎn)換一個(gè)可變長(zhǎng)列;必須對(duì)它們?nèi)窟M(jìn)行轉(zhuǎn)換。而且必須使用一個(gè)ALTE RTABLE 語(yǔ)句同時(shí)全部轉(zhuǎn)換,否則轉(zhuǎn)換將不起作用。
    ■ 有時(shí)不能使用定長(zhǎng)類(lèi)型,即使想這樣做也不行。例如對(duì)于比255 字符長(zhǎng)的串,沒(méi)有定長(zhǎng)類(lèi)型。
    4. 可索引類(lèi)型
    索引能加快查詢(xún)速度,因此,應(yīng)該選擇可索引的類(lèi)型。
    5. NULL 與NOT NULL 類(lèi)型
    如果定義一列為NOT NULL,其處理更快,因?yàn)镸ySQL 在查詢(xún)處理中不必檢查該列的值弄清它是否為N U L L,表中每行還能節(jié)省一位。避免列中有NULL 可以使查詢(xún)更簡(jiǎn)單,因?yàn)椴恍枰獙ULL 作為一種特殊情形來(lái)考慮。通常,查詢(xún)?cè)胶?jiǎn)單,處理就越快。所給出的性能準(zhǔn)則有時(shí)是互相矛盾的。例如,根據(jù)MySQL 能對(duì)行定位這一方面來(lái)說(shuō),包含CHAR 列的定長(zhǎng)行比包含VARCHAR 列的可變長(zhǎng)行處理快。但另一方面,它也將占用更多的空間,因此,會(huì)導(dǎo)致更多的磁盤(pán)活動(dòng)。從這個(gè)觀點(diǎn)來(lái)看, VARCHAR 可能會(huì)更快。作為一個(gè)經(jīng)驗(yàn)規(guī)則,可假定定長(zhǎng)列能改善性能,即使它占用更多的空間也如此。對(duì)于某個(gè)特殊的關(guān)鍵應(yīng)用,可能會(huì)希望以定長(zhǎng)和可變長(zhǎng)兩種方式實(shí)現(xiàn)一個(gè)表,并進(jìn)行某些測(cè)試以決定哪種方式對(duì)您的特定應(yīng)用來(lái)說(shuō)更快。
    2.3.4 希望對(duì)值進(jìn)行什么樣的比較
    根據(jù)定義串的方式,可以使串類(lèi)型以區(qū)分大小寫(xiě)或不區(qū)分大小寫(xiě)的方式進(jìn)行比較和排序。表2-14 示出不區(qū)分大小寫(xiě)的每個(gè)類(lèi)型及其等價(jià)的區(qū)分大小寫(xiě)類(lèi)型。根據(jù)列定義中給不給出關(guān)鍵字B I N A RY,有的類(lèi)型(C H A R、VA R C H A R)是二進(jìn)制編碼或非二進(jìn)制編碼的。其他類(lèi)型(B L O B、T E X T)的“二進(jìn)制化”隱含在類(lèi)型名中。

    請(qǐng)注意,二進(jìn)制(區(qū)分大小寫(xiě))類(lèi)型僅在比較和排序行為上不同于相應(yīng)的非二進(jìn)制(不區(qū)分大小寫(xiě))類(lèi)型。任意串類(lèi)型都可以包含任意種類(lèi)的數(shù)據(jù)。特別是, TEXT 類(lèi)型盡管在列類(lèi)型名中稱(chēng)為“T E X T(文本)”,但它可以很好地存儲(chǔ)二進(jìn)制數(shù)據(jù)。如果希望使用一個(gè)在比較時(shí)既區(qū)分大小寫(xiě),又可不區(qū)分大小寫(xiě)的列??稍谙MM(jìn)行區(qū)分大小寫(xiě)的比較時(shí),利用B I N A RY 關(guān)鍵字強(qiáng)制串作為二進(jìn)制串值。例如,如果my_col 為一個(gè)CHAR 列,可按不同的方式對(duì)其進(jìn)行比較:
    my_col = “A B C” 不區(qū)分大小寫(xiě)
    BINARY my_col =“A B C” 區(qū)分大小寫(xiě)
    my_col = BINARY“A B C” 區(qū)分大小寫(xiě)
    如果有一個(gè)希望以非字典順序存儲(chǔ)的串值,可考慮使用ENUM 列。ENUM 值的排序是根據(jù)列定義中所列出枚舉值的順序進(jìn)行的,因此可以使這些值以任意想要的次序排序。
    2.3.5 計(jì)劃對(duì)列進(jìn)行索引嗎
    使用索引可更有效地處理查詢(xún)。索引的選擇是第4 章中的一個(gè)主題,但一般原則是將WHERE 子句中用來(lái)選擇行的列用于索引。如果您要對(duì)某列進(jìn)行索引或?qū)⒃摿邪诙嗔兴饕?,則在類(lèi)型的選擇上可能會(huì)有限定。在早于3.23.2 版的MySQL 發(fā)行版中,索引列必須定義為NOT NULL,并且不能對(duì)BLOB 或TEXT 類(lèi)型進(jìn)行索引。這些限制在MySQL 3.23.2 版中都撤消了,但如果您正使用一個(gè)更早的版本,不能或不愿升級(jí),那么必須遵從這些約束。不過(guò)在下列情形中可以繞過(guò)它們:
    ■ 如果可以指定某個(gè)值作為專(zhuān)用的值,那么能夠?qū)⑵渥鳛榕cNULL 相同的東西對(duì)待。對(duì)于DATE 列,可以指定“0000 - 00 - 00”表示“無(wú)日期”。在串列中,可以指定空串代表“缺值”。在數(shù)值列中,如果該列一般只存儲(chǔ)非負(fù)值,則可使用- 1。
    ■ 不能對(duì)BLOB 或TEXT 類(lèi)型進(jìn)行索引,但如果串不超過(guò)255 它符,可使用等價(jià)的VARCHAR 列類(lèi)型并對(duì)其進(jìn)行索引??蒝ARCHAR(255) BINARY 用于BLOB 值,將VARCHAR(255) 用于TEXT 值。
    2.3.6 列類(lèi)型選擇問(wèn)題的相互關(guān)聯(lián)程度
    不要以為列類(lèi)型的選擇是相互獨(dú)立的。例如,數(shù)值的取值范圍與存儲(chǔ)大小有關(guān);在增大取值的范圍時(shí),需要更多的存儲(chǔ)空間,這會(huì)影響性能。另外,考慮選擇使用A U TO _INCREMENT 來(lái)創(chuàng)建一個(gè)存放唯一序列號(hào)的列有何含義。這個(gè)選擇有幾個(gè)結(jié)果,它們涉及列
的類(lèi)型、索引和NULL 的使用,現(xiàn)列出如下:
    ■ A U TO_INCREMENT 是一個(gè)應(yīng)該只用于整數(shù)類(lèi)型的列屬性。它將您的選擇限定在TINYINT 到BIGINT 之上。
    ■ A U TO_INCREMENT 列應(yīng)該進(jìn)行索引,從而當(dāng)前最大的序列號(hào)可以很快就確定,不用對(duì)表進(jìn)行全部掃描。此外,為了防止序列號(hào)被重用,索引號(hào)必須是唯一的。這表示必須將列定義為P R I M A RY KEY 或定義為UNIQUE 索引。
    ■ 如果所用的MySQL 版本早于3 . 2 3 . 2,則索引列不能包含NULL 值,因此,必須定義列為NOT NULL。所有這一切表示,不能像如下這樣只定義一個(gè)A U TO_INCREMENT 列:

    使用A U TO_INCREMENT 得到的另一個(gè)結(jié)果是,由于它是用來(lái)生成一個(gè)正值序列的,因此,最好將A U TO_INCREMENT 列定義為UNSIGNED:


破釜沉舟 http://www.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多