選擇優化的數據類型
更小的通常更好
一般情況下盡量使用可以正確存儲數據的最小類型。更小的數據類型通常更快,因為它們占用更少的磁盤,內存和CPU緩存,并且處理時需要的CPU周期也更少。但也要確保沒有低估需要存儲值的范圍。
簡單就好
簡單的數據類型通常需要更少的CPU周期。例如:整型比字符操作代價更低,因為字符集和校對規則(排序規則)使字符比較比整型比較更復雜。例如:應該使用 mysql 的內建類型而不是字符來存儲日期和時間,另外一個應該使用整型存儲IP地址。
盡量避免 NULL
NULL 使得索引、索引統計和值比較都更復雜
實數類型
DECIMAL 類型用于存儲精確的小數。因為CPU 不支持對 DECIMAL 的直接計算,所以在 Mysql 5.0 和更高版本中,Mysql 服務器自身實現了 Decimal 的高精度計算。相對而言,CPU 直接支持原生浮點計算,所以浮點運算明顯更快。Decimal 只是一種存儲格式,在計算中 Decimal 會轉換為 Double 類型。有時候也可以使用 Bigint 替代浮點型。
字符串類型
Varchar
Varchar 節省了存儲空間,所以對性能也有幫助。但是,由于是變長的,在 Update 時可能使行長變得比原來更長,這就導致需要做額外的工作,比如導致頻繁的頁分裂和合并,從而產生大量磁盤碎片。
Char
Char 類型是定長的,當存儲 Char 時, Mysql 會刪除所有的末尾空格。對于經常變更的數據也不容易產生磁盤碎片。
[!NOTE] 慷慨是不明智的
更長的列會消耗更多的內存,因為 Mysql 通常會分配固定大小的內存塊來保存內部值。尤其是使用內存臨時表進行排序或操作時會特別糟糕。在使用磁盤臨時表進行排序時也同樣糟糕。
所以最好的策略是只分配真正需要的空間
BLOB 和 TEXT
Mysql 對 BLOB 和 TEXT 列進行排序與其它類型是不同的:它只對每個列的最前 max_sort_length 字節而不是整個字符串做排序。Memory 引擎不支持 BLOB 和 TEXT 類型,因此在包含 BLOB 和 TEXT 類型的列都會轉而使用 MyIsam 磁盤臨時表。
日期和時間類型
TIMESTAMP
TIMESTAMP 顯示的值也依賴于時區
DATETIME
它把日期和時間封裝到格式為 YYYYMMDDHHMMSS 的整數中,與時區無關。
[!NOTE] TIPS
有時候人們會將 UNIX時間戳存儲為整數,但這將不會帶來任何收益。用整數保存時間戳的格式通常不方便處理,所以我們不推薦這樣做。
選擇標識符
當選擇標識列的類型時,不僅僅需要考慮存儲類型,還需要考慮 Mysql 對這種類型怎么計算和比較。一旦選定了一種類型,要確保在所有關聯表中都使用同樣的類型。類型之間需要精確匹配,包括像 UNSIGNED 這樣的屬性。混用不同數據類型可能導致性能問題,即使沒有性能影響,在比較操作時隱式類型轉換也可能導致很難發現的錯誤。
選擇合適的主鍵
大多數情況使用自增主鍵ID就可以解決問題,但當我們預估系統會有比較大的業務增長時,可以考慮使用分布式ID作為業務主鍵,避免后面分庫分表時帶來的不便
MySQL schema 設計中的陷阱
太多的列
MySQL 的存儲引擎API工作時需要在服務器層和存儲引擎層之間通過行緩沖格式拷貝數據,然后在服務器層將緩沖內容解碼成各個列。從行緩沖格式將編碼過的列轉換成行數據結構的操作代價是非常高的。這個過程是CPU密集型的(太多的列會導致CPU占用過高)。
太多的關聯
盡量不關聯或者少關聯表