4.3 列類型選擇與查詢效率
要選擇有助于使查詢執行更快的列,應遵循如下規則(這里,“blob 類型”應該理解為即包含b l o b也包含text 類型):
■ 使用定長列,不使用可變長列。這條準則對被經常修改,從而容易產生碎片的表來說特別重要。例如,應該選擇char 列而不選擇varchar 列。所要權衡的是使用定長列時,表所占用的空間更多,但如果能夠承擔這種占淶暮姆眩褂枚ǔば薪仁褂每殺涑さ男寫砜斕枚唷?br> ■ 在較短的列能夠滿足要求時不要使用較長的列。如果正使用的是定長的char 列,應該使它們盡量短。如果列中所存儲的最長值為40 個字符,那么就不要將其定義為char ( 2 5 5 );只要定義為char(40) 即可。如果能夠使用mediumint 而不是bigint,表將會更小(磁盤i/o 也較少),其值在計算中也可以處理得更快。
■ 將列定義為not null。這樣處理更快,所需空間更少。而且有時還能簡化查詢,因為不需要檢查是否存在特例null。
■ 考慮使用enum 列。如果有一個只含有限數目的特定值的列,那么應該考慮將其轉換為enum 列。enum 列的值可以更快地處理,因為它們在內部是以數值表示的。
■ 使用procedure analyse( )。如果使用的是mysql3.23 或更新的版本,應該執行procedure analyse( ),查看它所提供的關于表中列的信息:
相應輸出中有一列是關于表中每列的最佳列類型的建議。第二個例子要求procedure analyse( ) 不要建議含有多于16 個值或取多于256 字節的enum 類型(可根據需要更改這些值)。如果沒有這樣的限制,輸出可能會很長;enum 的定義也會很難閱讀。根據procedure analyse( ) 的輸出,會發現可以對表進行更改以利用更有效的類型。如果希望更改值類型,使用alter table 語句即可。
■ 將數據裝入b l o b。用blob 存儲應用程序中包裝或未包裝的數據,有可能使原來需要幾個檢索操作才能完成的數據檢索得以在單個檢索操作中完成。而且還對存儲標準表結構不易表示的數據或隨時間變化的數據有幫助。在第3 章alter table 語句的介紹中,有一個例子處理存儲來自web 問卷的結果的表。該例子中討論了在問卷中增加問題時,怎樣利用alter table 向該表追加列。
解決該問題的另一個方法是讓處理web 的應用程序將數據包裝成某種數據結構,然后將其插入單個blob 列。這樣會增加應用程序對數據進行解碼的開銷(而且從表中檢索出記錄后要對其進行編碼),但是簡化了表的結構,并且不用在更改問卷時對表進行更改。另一方面, blob 值也有自己的固有問題,特別是在進行大量的delete 或update 操作時更是如此。刪除blob 會在表中留下一個大空白,在以后將需用一個記錄或可能是不同大小的多個記錄來填充。
■ 對容易產生碎片的表使用optimize table。大量進行修改的表,特別是那些含有可變長列的表,容易產生碎片。碎片不好,因為它在存儲表的磁盤塊中產生不使用的空間。隨著時間的增長,必須讀取更多的塊才能取到有效的行,從而降低了性能。任意具有可變長行的表都存在這個問題,但這個問題對blob 列更為突出,因為它們尺寸的變化非常大。經常使用optimize table 有助于保持性能不下降。
■ 使用合成索引。合成索引列有時很有用。一種技術是根據其他列建立一個散列值,并將其存儲在一個獨立的列中,然后可通過搜索散列值找到行。這只對精確匹配的查詢有效。(散列值對具有諸如“ <”或“ > =”這樣的操作符的范圍搜索沒有用處)。在mysql3.23版及以上版本中,散列值可利用md5( ) 函數產生。散列索引對blob 列特別有用。有一事要注意,在mysql3.23.2 以前的版本中,不能索引blob 類型。甚至是在3.23.2 或更新的版本中,利用散列值作為標識值來查找blob 值也比搜索blob 列本身更快。
■ 除非有必要,否則應避免檢索較大的blob 或text 值。例如,除非肯定where 子句能夠將結果恰好限制在所想要的行上,否則select * 查詢不是一個好辦法。這樣做可能會將非常大的blob 值無目的地從網絡上拖過來。這是存儲在另一列中的blob 標識信息很有用的另一種情形。可以搜索該列以確定想要的行,然后從限定的行中檢索blob 值。
■ 將blob 值隔離在一個獨立的表中。在某些情況下,將blob 列從表中移出放入另一個副表可能具有一定的意義,條件是移出blob 列后可將表轉換為定長行格式。這樣會減少主表中的碎片,而且能利用定長行的性能優勢。
新聞熱點
疑難解答