MySQL 高性能表設(shè)計規(guī)范

相關(guān)文章:

MySQL高性能表設(shè)計規(guī)范:http://www.reibang.com/p/f797bbe11d76
MySQL EXPLAIN詳解:http://www.reibang.com/p/ea3fc71fdc45
MySQL 鎖機制 常用知識點:http://www.reibang.com/p/0d5b7cd592f9
image.png

良好的邏輯設(shè)計和物理設(shè)計是高性能的基石寞肖, 應該根據(jù)系統(tǒng)將要執(zhí)行的查詢語句來設(shè)計schema, 這往往需要權(quán)衡各種因素抚芦。

一模狭、選擇優(yōu)化的數(shù)據(jù)類型

MySQL支持的數(shù)據(jù)類型非常多, 選擇正確的數(shù)據(jù)類型對于獲得高性能至關(guān)重要蝌借。

更小的通常更好

更小的數(shù)據(jù)類型通常更快卿啡, 因為它們占用更少的磁盤吟吝、 內(nèi)存和CPU緩存, 并且處理時需要的CPU周期也更少颈娜。

簡單就好

簡單數(shù)據(jù)類型的操作通常需要更少的CPU周期剑逃。 例如, 整型比字符操作代價更低官辽, 因為字符集和校對規(guī)則(排序規(guī)則 )使字符比較比整型比較更復雜蛹磺。

盡量避免NULL

如果查詢中包含可為NULL 的列, 對MySQL來說更難優(yōu)化同仆, 因為可為NULL 的列使得索引萤捆、 索引統(tǒng)計和值比較都更復雜。 可為NULL的列會使用更多的存儲空間乓梨, 在MySQL里也需要特殊處理鳖轰。 當可為NULL的列被索引時清酥, 每個索引記錄需要一個額外的字節(jié)扶镀, 在MyISAM里甚至還可能導致固定大小的索引(例如只有一個整數(shù)列的索引)變成可變大小的索引。
當然也有例外焰轻, 例如InnoDB 使用單獨的位 (bit) 存儲NULL值臭觉, 所以對于稀疏數(shù)據(jù)有很好的空間效率。

1.整數(shù)類型

有兩種類型的數(shù)字:整數(shù) (whole number) 和實數(shù) (real number) 辱志。 如果存儲整數(shù)蝠筑, 可以使用這幾種整數(shù)類型:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT。分別使用8,16, 24, 32, 64位存儲空間揩懒。

整數(shù)類型有可選的 UNSIGNED 屬性什乙,表示不允許負值,這大致可以使正數(shù)的上限提高一倍已球。 例如 TINYINT. UNSIGNED 可以存儲的范圍是 0 - 255, 而 TINYINT 的存儲范圍是 -128 -127 臣镣。

有符號和無符號類型使用相同的存儲空間,并具有相同的性能 智亮, 因此可以根據(jù)實際情況選擇合適的類型忆某。

你的選擇決定 MySQL 是怎么在內(nèi)存和磁盤中保存數(shù)據(jù)的。 然而阔蛉, 整數(shù)計算一般使用64 位的 BIGINT 整數(shù)弃舒, 即使在 32 位環(huán)境也是如此。( 一些聚合函數(shù)是例外状原, 它們使用DECIMAL 或 DOUBLE 進行計算)聋呢。

MySQL 可以為整數(shù)類型指定寬度苗踪, 例如 INT(11), 對大多數(shù)應用這是沒有意義的:它不會限制值的合法范圍,只是規(guī)定了MySQL 的一些交互工具(例如 MySQL 命令行客戶端)用來顯示字符的個數(shù)削锰。 對于存儲和計算來說徒探, INT(1) 和 INT(20) 是相同的。

2.實數(shù)類型

實數(shù)是帶有小數(shù)部分的數(shù)字喂窟。 然而测暗, 它們不只是為了存儲小數(shù)部分,也可以使用DECIMAL 存儲比 BIGINT 還大的整數(shù)磨澡。

FLOAT和DOUBLE類型支持使用標準的浮點運算進行近似計算碗啄。
DECIMAL類型用于存儲精確的小數(shù)。
浮點和DECIMAL類型都可以指定精度稳摄。 對于DECIMAL列稚字, 可以指定小數(shù)點前后所允許的最大位數(shù)。這會影響列的空間消耗厦酬。

有多種方法可以指定浮點列所需要的精度胆描, 這會使得MySQL選擇不同的數(shù)據(jù)類型,或者在存儲時對值進行取舍仗阅。 這些精度定義是非標準的昌讲,所以我們建議只指定數(shù)據(jù)類型,不指定精度减噪。

浮點類型在存儲同樣范圍的值時短绸, 通常比DECIMAL使用更少的空間。FLOAT使用4個字節(jié)存儲筹裕。DOUBLE占用8個字節(jié)醋闭,相比FLOAT有更高的精度和更大的范圍。和整數(shù)類型一樣朝卒, 能選擇的只是存儲類型证逻; MySQL使用DOUBLE作為內(nèi)部浮點計算的類型。

因為需要額外的空間和計算開銷抗斤,所以應該盡量只在對小數(shù)進行精確計算時才使用DECIMAL囚企。但在數(shù)據(jù)最比較大的時候, 可以考慮使用BIGINT代替DECIMAL, 將需要存儲的貨幣單位根據(jù)小數(shù)的位數(shù)乘以相應的倍數(shù)即可豪治。

3.字符串類型

VARCHAR

用于存儲可變?字符串洞拨,長度支持到65535
需要使用1或2個額外字節(jié)記錄字符串的長度
適合:字符串的最大?度比平均?度?很多;更新很少

CHAR

定?负拟,?度范圍是1~255
適合:存儲很短的字符串烦衣,或者所有值接近同一個長度;經(jīng)常變更

慷慨是不明智的

使用VARCHAR(5)和VARCHAR(200)存儲'hello'的空間開銷是一樣的。 那么使用更短的列有什么優(yōu)勢嗎花吟?

事實證明有很大的優(yōu)勢秸歧。 更長的列會消耗更多的內(nèi)存, 因為MySQL通常會分配固定大小的內(nèi)存塊來保存內(nèi)部值衅澈。 尤其是使用內(nèi)存臨時表進行排序或操作時會特別糟糕键菱。 在利用磁盤臨時表進行排序時也同樣糟糕。

所以最好的策略是只分配真正需要的空間今布。

4.BLOB和TEXT類型

BLOB和 TEXT都是為存儲很大的數(shù)據(jù)而設(shè)計的字符串數(shù)據(jù)類型经备, 分別采用 二進制和字符方式存儲 。

與其他類型不同部默, MySQL把每個BLOB和TEXT值當作一個獨立的對象處理侵蒙。 存儲引擎在存儲時通常會做特殊處理。 當BLOB和TEXT值太大時傅蹂,InnoDB會使用專門的 “外部“存儲區(qū)域來進行存儲纷闺, 此時每個值在行內(nèi)需要1 - 4個字節(jié)存儲 存儲區(qū)域存儲實際的值。

BLOB 和 TEXT 之間僅有的不同是 BLOB 類型存儲的是二進制數(shù)據(jù)份蝴, 沒有排序規(guī)則或字符集犁功, 而 TEXT類型有字符集和排序規(guī)則

5.日期和時間類型

大部分時間類型都沒有替代品, 因此沒有什么是最佳選擇的問題婚夫。 唯一的問題是保存日期和時間的時候需要做什么浸卦。 MySQL提供兩種相似的日期類型: DATE TIME和 TIMESTAMP。

但是目前我們更建議存儲時間戳的方式请敦,因此該處不再對 DATE TIME和 TIMESTAMP做過多說明镐躲。

5.其他類型

5.1選擇標識符

在可以滿足值的范圍的需求, 井且預留未來增長空間的前提下侍筛, 應該選擇最小的數(shù)據(jù)類型。

整數(shù)類型

整數(shù)通常是標識列最好的選擇撒穷, 因為它們很快并且可以使用AUTO_INCREMENT匣椰。

ENUM和SET類型

對于標識列來說,EMUM和SET類型通常是一個糟糕的選擇端礼, 盡管對某些只包含固定狀態(tài)或者類型的靜態(tài) ”定義表” 來說可能是沒有問題的禽笑。ENUM和SET列適合存儲固定信息, 例如有序的狀態(tài)蛤奥、 產(chǎn)品類型佳镜、 人的性別。

字符串類型

如果可能凡桥, 應該避免使用字符串類型作為標識列蟀伸, 因為它們很消耗空間, 并且通常比數(shù)字類型慢。

對于完全 “隨機” 的字符串也需要多加注意啊掏, 例如 MDS() 蠢络、 SHAl() 或者 UUID() 產(chǎn)生的字符串。 這些函數(shù)生成的新值會任意分布在很大的空間內(nèi)迟蜜, 這會導致 INSERT 以及一些SELECT語句變得很慢刹孔。如果存儲 UUID 值, 則應該移除 "-"符號娜睛。

5.2特殊類型數(shù)據(jù)

某些類型的數(shù)據(jù)井不直接與內(nèi)置類型一致髓霞。 低千秒級精度的時間戳就是一個例子,另一個例子是以個1Pv4地址畦戒,人們經(jīng)常使用VARCHAR(15)列來存儲IP地址酸茴,然而, 它們實際上是32位無符號整數(shù)兢交, 不是字符串薪捍。用小數(shù)點將地址分成四段的表示方法只是為了讓人們閱讀容易。所以應該用無符號整數(shù)存儲IP地址配喳。MySQL提供INET_ATON()和INET_NTOA()函數(shù)在這兩種表示方法之間轉(zhuǎn)換酪穿。

二、表結(jié)構(gòu)設(shè)計

1.范式和反范式

對于任何給定的數(shù)據(jù)通常都有很多種表示方法晴裹, 從完全的范式化到完全的反范式化被济, 以及兩者的折中。 在范式化的數(shù)據(jù)庫中涧团, 每個事實數(shù)據(jù)會出現(xiàn)并且只出現(xiàn)一次只磷。 相反, 在反范式化的數(shù)據(jù)庫中泌绣, 信息是冗余的钮追, 可能會存儲在多個地方。

范式的優(yōu)點和缺點

為性能提升考慮時阿迈,經(jīng)常會被建議對 schema 進行范式化設(shè)計元媚,尤其是寫密集的場景。

  • 范式化的更新操作通常比反范式化要快苗沧。
  • 當數(shù)據(jù)較好地范式化時刊棕,就只有很少或者沒有重復數(shù)據(jù),所以只需要修改更少的數(shù)據(jù)待逞。
  • 范式化的表通常更小甥角,可以更好地放在內(nèi)存里,所以執(zhí)行操作會更快识樱。
  • 很少有多余的數(shù)據(jù)意味著檢索列表數(shù)據(jù)時更少需要 DISTINCT 或者 GROUP BY語句嗤无。

反范式的優(yōu)點和缺點

不需要關(guān)聯(lián)表震束,則對大部分查詢最差的情況——即使表沒有使用索引——是全表掃描。 當數(shù)據(jù)比內(nèi)存大時這可能比關(guān)聯(lián)要快得多翁巍,因為這樣避免了隨機I/0驴一。

單獨的表也能使用更有效的索引策略。

混用范式化和反范式化

在實際應用中經(jīng)常需要混用灶壶,可能使用部分范式化的 schema 肝断、 緩存表,以及其他技巧驰凛。
表適當增加冗余字段胸懈,如性能優(yōu)先,但會增加復雜度恰响∪で可避免表關(guān)聯(lián)查詢。

簡單熟悉數(shù)據(jù)庫范式

第一范式(1NF):字段值具有原子性,不能再分(所有關(guān)系型數(shù)據(jù)庫系統(tǒng)都滿足第一范式);
            例如:姓名字段,其中姓和名是一個整體,如果區(qū)分姓和名那么必須設(shè)立兩個獨立字段;
         
第二范式(2NF):一個表必須有主鍵,即每行數(shù)據(jù)都能被唯一的區(qū)分;
            備注:必須先滿足第一范式;
         
第三范式(3NF):一個表中不能包涵其他相關(guān)表中非關(guān)鍵字段的信息,即數(shù)據(jù)表不能有沉余字段;
            備注:必須先滿足第二范式;

2.表字段少?精

  • I/O高效
  • 字段分開維護簡單
  • 單表1G體積 500W?行評估
  • 單?行不超過200Byte
  • 單表不超過50個INT字段
  • 單表不超過20個CHAR(10)字段
  • 建議單表字段數(shù)控制在20個以內(nèi)
  • 拆分TEXT/BLOB胚宦,TEXT類型處理性能遠低于VARCHAR首有,強制生成硬盤臨時表浪費更多空間。

參考資料:

高性能mysql第三版


個人介紹:

高廣超 :多年一線互聯(lián)網(wǎng)研發(fā)與架構(gòu)設(shè)計經(jīng)驗枢劝,擅長設(shè)計與落地高可用井联、高性能互聯(lián)網(wǎng)架構(gòu)。

本文首發(fā)在 高廣超的簡書博客 轉(zhuǎn)載請注明您旁!

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末烙常,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鹤盒,更是在濱河造成了極大的恐慌蚕脏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侦锯,死亡現(xiàn)場離奇詭異驼鞭,居然都是意外死亡,警方通過查閱死者的電腦和手機率触,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門终议,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人葱蝗,你說我怎么就攤上這事∠噶牵” “怎么了两曼?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長玻驻。 經(jīng)常有香客問我悼凑,道長偿枕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任户辫,我火速辦了婚禮渐夸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渔欢。我一直安慰自己墓塌,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布奥额。 她就那樣靜靜地躺著苫幢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垫挨。 梳的紋絲不亂的頭發(fā)上韩肝,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音九榔,去河邊找鬼哀峻。 笑死,一個胖子當著我的面吹牛哲泊,可吹牛的內(nèi)容都是我干的剩蟀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼攻旦,長吁一口氣:“原來是場噩夢啊……” “哼喻旷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起牢屋,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤且预,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烙无,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锋谐,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年截酷,在試婚紗的時候發(fā)現(xiàn)自己被綠了涮拗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡迂苛,死狀恐怖三热,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情三幻,我是刑警寧澤就漾,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站念搬,受9級特大地震影響抑堡,放射性物質(zhì)發(fā)生泄漏摆出。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一首妖、第九天 我趴在偏房一處隱蔽的房頂上張望偎漫。 院中可真熱鬧,春花似錦有缆、人聲如沸象踊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽通危。三九已至,卻和暖如春灌曙,著一層夾襖步出監(jiān)牢的瞬間菊碟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工在刺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逆害,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓蚣驼,卻偏偏與公主長得像魄幕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颖杏,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容