MySQL Schema與資料型別優化

2021-07-23 23:57:05 字數 3116 閱讀 5489

mysql支援的資料型別非常多,選擇正確的資料型別對於獲得高效能至關重要。不管儲存哪種型別的資料,下面幾個簡單原則都有助於做出更好的選擇。

一般情況下,應該盡量使用可以正確儲存資料的最小資料型別。更小的資料型別通常更快,因為它們占用更少的磁碟、記憶體和cpu快取,並且處理時需要的cpu週期也更少。

簡單資料型別的操作通常需要更少的cpu週期。例如,整型比字串操作代價更低,因為字符集和校對規則(排序規則)使字串比較比整型更複雜。

很多表都包含可為null(空值)的列,即使應用程式並不需要儲存null也是如此,這是因為可為null是列的預設屬性。通常情況下,最好知道列為not null,除非真的需要儲存null值。

如果查詢中包含可為null的列,對於mysql來說更難優化,因為可為null的列使得索引、索引統計和值比較都更複雜。可為null的列會使用更多的儲存空間,在mysql裡也需要特殊處理。當可為null 的列被索引時,每個索引記錄需要乙個額外的自己,在myisam裡還可能到固定大小的索引(例如只有乙個整數列的索引)變成可變大小的索引。

通常把可為null的列改為 not null帶來的效能提公升比較小,所以(調優時)沒有必要首先在現有schema中查詢並修改掉這種情況,除非確定這會導致問題。但是,如果計畫在列上建索引,就應該盡量避免設計成可為null的列。

對於整數型別,可以使用 tinyint、 smallint、 mediumint、 int、 bigint 等。每個整數型別都對應著不同的儲存空間。

資料型別

儲存(byte)

tinyint

1smallint

2mediumint

3int

4bigint

8 整數型別可以選擇 unsigned 屬性,表示不允許負值,這樣可以使得正數的上限提高一倍。舉個例子,tinyint 的儲存範圍是 -2-7 ~ 27 - 1,也就是 -128 ~ 127,那麼 unsigned int 可以儲存的範圍就是 0 ~ 28 - 1,即 0 ~ 255。

mysql可以為整數型別指定寬度,然而對大多數場景是沒有意義的:它並不會限制整數型別的合法範圍,它只是規定某些互動工具顯示出來的字元個數。如果不顯示地指定寬度,則預設為 int(11)。有讀者會誤認為 int(11) 指定整數型別的長度是 11 位,這個想法是錯誤的。實際上,在 zerofill 屬性中,表示當陣列寬度小於 11 位時,在數字前面加 0 填滿寬度。

對於實數型別,可以使用 float、 double、 decimal 等。每個實數型別都對應著不同的儲存空間。

資料型別

儲存(byte)

float

4double

8 float(m,d) 和 double(m,d) 表示一共顯示 m 位整數,d 位小數。

舉個例子,float(5,2) 可以顯示為 100.99。此外,讀者還要注意的是,mysql 儲存時會進行四捨五入,因此,如果值為 100.0099, 會儲存近似結果 100.01。

float 只保證 6 位有效數字的準確性,所以 float(m,d) 中,m<=6 時,數字通常是準確的。

double 只保證 16 位有效數字的準確性,所以 double(m,d) 中,m<=16 時,數字通常是準確的。

在使用實數型別,要重點考慮精度問題。double 是 mysql 內部浮點計算的型別,它比 float 有更高的精度和更大的範圍,但是 float 和 double 都是不精確的,如果要實現精確浮點運算,就需要使用 decimal 型別(例如,儲存財務資料)。

但在資料量比較大的時候,可以考慮使用bigint 代替decimal ,將需要儲存的貨幣單位根據小數的位數乘以相應的倍數即可。假設要儲存財務資料精確到萬分之一,則可以把所有金額乘以一萬,然後將儲存結果儲存到bigint 裡,這樣可以同時避免浮點儲存技術不精確和decimal 精確計算代價高的問題。

mysql支援多種字串型別,可以使用 char、 varchar、 blob、 text 等。

char 型別是定長的。mysql 會根據定義的長度分配空間。char 長度可以是 0 到 255之間的值。

varchar 型別用於儲存可變長字串,它更加節省空間。值得注意的是, varchar 需要使用 1 或 2 個額外位元組記錄字串的長度:如果列的最大長度小於或者等於255,則只使用1個位元組表示,否則使用2個位元組。varchar 長度可以指定 0 到 65535 之間的值。

blob 和 text 主要用來儲存大文字,分別採用二進位制和字串方式儲存。

實際上,它們分別屬於兩組不同的資料型別載入:字串型別是 tinytext、 smalltext、text、mediumtext、 longtext。

對應二進位制型別是: tinyblob、smallblob、 blob 、mediumblob、 longblob。

mysql可以使用許多態別來儲存日期和時間值,例如: year、 date、 time、、 timestamp、datetime。

mysql 能夠儲存的最小單位是秒,如果需要更精確的儲存,就必須自己定義儲存格式。比如可以使用bigint儲存毫秒級別的時間戳。

datetime型別範圍:'101-01-01 00:00:00' ~ '9999-12-31 23:59:59'。

timestamp型別範圍:'1970-01-01 00:00:01'utc ~ '2038-01-19 03:14:07' utc

datetime 和 timestamp 都可以儲存相同型別的資料,而 timestamp 只使用 datetime 一半的儲存空間。通常情況下,建議優先考慮 timestamp,因為它的空間利用率更高。

對於任意給定的資料通常都有很多種表示方式,從完全的正規化化到完全的反正規化化,以及兩者的折中。在正規化化的資料庫中,每個資料會出現並且僅出現異常。相反,在反正規化化的資料庫中,資訊是冗餘的,可能會儲存在多個地方。

正規化化設計schema的優點:

正規化化的更新操作通常比反正規化化要快

當資料比較好地正規化化時,就只有很少或者沒有重複資料,所以只需要修改更少的資料。

正規化化的表通常更小,可以更好地放在記憶體裡,所以執行操作會更快。

正規化化設計schema的缺點是 通常需要關聯。稍微複雜一些的查詢語句在符合正規化化的

schema上都可能需要至少一次關聯,也許更多。

事實上, 完全的正規化化和完全的反正規化化 都是實驗室裡才有的東西,在真實世界中很少會這麼極端的去使用。在實際應用中 經常需要混用 正規化化和反正規化化。

Mysql Schema與資料型別的優化

mysql支援的資料型別非常多,有個簡單的選擇原則 與char和varchar相似的還有binary和varbinary,他們儲存的是二進位制字串,儲存的是位元組碼而不是字元。通常使用timestamp,空間效率更高。選擇識別符號 特殊資料型別 先禁用索引,載入資料,然後重新啟用索引 alter t...

Kotlin 資料類與密封類

資料類 kotlin 可以建立乙個只包含資料的類,關鍵字為 data data class user val name string,val age int 編譯器會自動的從主建構函式中根據所有宣告的屬性提取以下函式 equals hashcode tostring 格式如 user name jo...

Kotlin 資料類與密封類

kotlin可建立乙個只包含資料的類,關鍵字為data data class person val name string,val age int 編譯器會自動的從主建構函式中根據所有宣告的屬性提取以下函式 equals hashcode tostring 格式如 user name john,ag...