深刻學習MySQL 03 Schema與數據類型優化

Schema是什麼鬼

schema就是數據庫對象的集合,這個集合包含了各類對象如:表、視圖、存儲過程、索引等。爲了區分不一樣的集合,就須要給不一樣的集合起不一樣的名字,默認狀況下一個用戶對應一個集合,用戶的schema名等於用戶名,並做爲該用戶缺省schema。因此schema集合看上去像用戶名。html

若是把database看做是一個倉庫,倉庫不少房間(schema),一個schema表明一個房間,table能夠看做是每一個房間中的儲物櫃,user是每一個schema的主人,有操做數據庫中每一個房間的權利,就是說每一個數據庫映射的user有每一個schema(房間)的鑰匙。mysql

選擇優化的數據類型

選擇正確的數據類型對於得到高性能相當重要,一下3個原則能有助於更好的選擇。web

1.更小的一般更好
更小的數據類型一般更快,由於它們佔用更少的磁盤,內存,CPU。sql

2.簡單就好 簡單數據類型的操做一般須要更少的CPU週期。例如:整型比字符操做代價更低,由於字符集和校對規則使字符比較比整型比較更復雜。數據庫

3.儘可能避免NULL 一般狀況下最好制定列爲NOT NULL,除非真的須要存儲NULL值緩存

可爲NULL列的缺點:ide

  • 使得索引,索引統計和值比較都更復雜svg

  • 使用更多的存儲空間,在MySQL中也須要特殊處理函數

數據類型

整數

存儲整數可使用這幾種:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。分別使用8,16,24,32,64爲存儲空間。post

整數類型可選的UNSIGNED屬性,表示不容許負值,這大體可使正數的上限提升一倍。例如:TINYINT UNSIGNED能夠存儲的範圍是0~255,而TINYINT的存儲範圍是-128 ~ 127

有符號和無符號類型使用相同的存儲空間,且具備相同的性,所以根據實際狀況選取便可

實數:帶小數的數

3種數據類型能夠存儲實數:float,double,decimal

float和double存儲的數據有可能不許確,decimal可存儲精確小數,存儲財務數據或經度要求高時使用decimal

float和double不許確的緣由:mysql中float和double分別分配了32位、64位的存儲空間,當float、double類型的數據轉換爲二進制時,第32位/64位以後的數都會被截斷,從而形成數據有可能不許確

decimal的存儲須要額外的空間和計算開銷,因此應該儘可能只在對小數進行精確計算時才使用DECIMAL。在數據量比較大的時候,能夠考慮使用BIGINT代替DECIMAL,將對應的值擴大N倍。

字符串

char:

  • 長度範圍:0~255

  • 存儲:固定長度,存儲數據未達到指定長度時,右邊填充空格以達到指定的長度;當查詢CHAR值時,尾部的空格被刪除掉。

  • 優勢:效率高

varchar:

  • 長度範圍:0~65535

  • 存儲:可變長度,保存時只保存須要的字符數,另加一個字節來記錄長度(若是列聲明的長度超過255,則使用兩個字節);存儲數據未達到指定長度時不進行填充;當值保存和檢索時尾部的空格仍保留

  • 優勢:節省空間

須要分狀況來決定:
當肯定字符串爲定長、數據變動頻繁、數據檢索需求少時,使用char;
當不肯定字符串長度、對數據的變動少、查詢頻繁時,使用varchar。

大數據

blob:

  • 數據類型:tinyblob、smallblob、blob、mediumblob、longblob

  • 存儲:採用二進制方式存儲,無排序規則和字符集

text:

  • 數據類型:tinytext、smalltext、text、mediumtext、longtext

  • 存儲:採用字符方式存儲,有排序規則和字符集

MySQL會把每一個blob和text當作獨立的對象處理,存儲引擎存儲時會作特殊處理,當值太大,innoDB使用專門的外部存儲區域進行存儲,行內存儲指針,而後在外部存儲實際的值;

mysql對他們的列排序:只對每列前max_sort_length字節排序,且不能將列所有長度的字符串進行索引

日期和時間

datetime:

  • 範圍:1001年~9999年

  • 存儲:8個字節存儲,以YYYYMMDDHHMMSS的格式存儲,與時區無關

timestamp:

  • 範圍:1970年~2038年

  • 存儲:4個字節存儲,存儲格式與UNIX時間戳相同,與時區有關

1.一般儘可能使用timestamp,由於它的空間效率高

2.可使用BIGINT類型存儲微秒級別的時間戳

選擇標識符(identifier,主鍵)
  • 整數類型一般是標識列最好的選擇,由於它們很快而且可使用AUTO_INCREMENT

  • 應該避免使用字符串類型做爲標識列,由於它們很消耗空間,而且一般比數字類型慢

  • 對於徹底"隨機"的字符串也須要多加註意。例如:MD5(),SHAI()或者UUID()產生的字符串。這些函數生成的新值也任意分佈在很大空間內,這會致使INSERT和一些SELECT語句很緩慢

  • 要確保在全部關聯表中的外鍵與主鍵使用一樣的類型。用不一樣數據類型可能致使性能問題或在比較操做時隱式類型轉換也可能致使很難發現錯誤。

另外

IP地址實際是32位無符號整數,MySQL提供INET_ATON()和INET_NTOA()函數在這兩種表示方法之間轉換。(inet_ntoa(3507806248)  --> 209.20.224.40 )

範式和反範式

一般建議使用範式化設計,由於範式化一般會使得執行操做更快。但這並非絕對的,範式化也是有缺點的,一般須要關聯查詢,不只代價昂貴,也可能使一些索引策略無效。

因此,咱們有時須要混同範式化和反範式化,好比一個更新頻率低的字段能夠冗餘在別的表中,避免關聯查詢

緩存表和彙總表

  • 緩存表:存儲那些能夠比較容易的從schema其餘表獲取(但每次獲取速度緩慢)數據的表

  • 彙總表:保存的是使用GROUP BY語句聚合數據的表。實時計算統計值是很昂貴的操做。

在使用緩存表和彙總表時,必須決定是實時維護數據仍是按期重建。哪一個更好依賴於應用程序,可是按期重建並不僅是節省資源,能夠保持表不會有不少碎片,以及徹底順序組織的索引。

總結

  • 使用小而簡單的合適數據類型

  • 儘可能避免使用NULL值

  • 關聯條件中使用的列儘可能使用相同的數據類型

  • 儘可能使用整型作主鍵

  • 切勿過分範式化,範式化與反範式化混用有時是最好的選擇

參考:
《高性能MySql》
https://www.cnblogs.com/csniper/p/5509620.html
http://blog.leanote.com/post/weibo-007/mysql_float_double_decimal
https://www.cnblogs.com/Jtianlin/p/5143873.html

若是以爲不錯,分享給你的朋友!

一個立志成大腿而天天努力奮鬥的年輕人

伴學習伴成長,成長之路你並不孤單!

掃描二維碼,關注公衆號

相關文章
相關標籤/搜索