mysql字段优化_MySQL优化(1):字段的设计
Web項目中,當(dāng)Java或者Go等語言速度提升到瓶頸的時候,我們需要關(guān)心MySQL的優(yōu)化
可以優(yōu)化的方面有很多:設(shè)計表、負(fù)載均衡、讀寫分離、SQL語句優(yōu)化等
(1)IP地址設(shè)計
例如我們需要存儲IP地址:192.168.1.1
第一反應(yīng)是選用VARCHAR(15);但是更好的方式是INT UNSIGNED(占用四個字節(jié))
因為:IP地址可以很容易地轉(zhuǎn)換為無符號整數(shù)
仔細(xì)觀察IP地址,四部分都是0-255的數(shù)字,1個字節(jié)(8位)恰好可以表示0-255的整數(shù)
而MySQL有函數(shù):inet_aton():地址轉(zhuǎn)成數(shù)字,inet_ntoa():數(shù)字轉(zhuǎn)成地址
示例:
SELECT INET_ATON('192.168.0.1')
結(jié)果:3232235521
SELECT INET_NTOA("3232235521")
結(jié)果:192.168.0.1
INT UNSIGNED占用字節(jié)少于VARCHAR(15),并且整數(shù)查詢效率更高(代價是需要使用轉(zhuǎn)換函數(shù))
總結(jié):在設(shè)計字段的時候,盡量使用整數(shù)來表示字符串
(2)關(guān)聯(lián)表設(shè)計
整型的優(yōu)勢:固定存儲空間,通常是少量空間
例如:MySQL內(nèi)部的枚舉和集合類型:
enum(男,女,未知)
insert into user(gender) values(男)
這句話在MySQL中實(shí)際存儲的是1,這就是最典型的把字符串存成整數(shù)
注意:實(shí)際中,很少使用mysql的enum和set,因為維護(hù)成果過高
比如性別需要把未知改為人妖,需要執(zhí)行alter table modify column操作,需要獨(dú)占整張表,檢查記錄性別值的合法性
如果一定要使用這種方式:關(guān)聯(lián)表,字段id,title,存儲1,男,2,女。這種方式使用較為廣泛
但是,比如家庭地址這樣的字符串,是無法改成整型的,不能強(qiáng)行操作
(3)金額存儲
金額的存儲對數(shù)據(jù)的精度要求較高,按理來說要使用DECIMAL()
例如DECIMAL(10,2):有2位小數(shù)的定點(diǎn)數(shù)
實(shí)際中有另一種操作:INT或BIGINT,這時候為了精度不丟失,采用”分“為單位(12.51元記錄為1251)
計算機(jī)中小數(shù)是無法做到不損失精度的,但是金額較特殊,固定了兩位小數(shù),所以可以采用這種方式
而且編程中,整數(shù)的計算相對于小數(shù)較為方便
DECIMAL也有擅長的地方,比如存儲大數(shù):123456789123456789
這時候不可以使用INT,只能使用BIGINT或者DECIMAL
注意:這里為什么我們不選擇浮點(diǎn)數(shù)DOUBLE和FLOAT呢?因為浮點(diǎn)數(shù)會導(dǎo)致精度丟失
原因:浮點(diǎn)數(shù)占用固定的存儲空間,無論存儲多大的數(shù),空間是一定的;但是定點(diǎn)數(shù)空間會隨著數(shù)字變大而增加
由此引出了定長類型和變長類型:
定長類型:存儲空間固定(INT、FLOAT、DOUBLE、CHAR、DATE、TIME、DATETIME、YEAR、TIMESTAMP)
變長類型:存儲空間可變(VARCHAR、DECIMAL、TEXT)
注意:只有定長類型才會有損失精度的問題,定長類型效率較高
結(jié)論:在乎存儲空間采用定長類型,在乎存儲精度采用變長類型
(4)TEXT和VARCHAR的選擇
TEXT:通常感覺存儲容量較大,其實(shí)最大容量和VARCHAR的最大容量幾乎一樣
但是,TEXT是獨(dú)立存儲的,不占用字段的總空間,但是VARCHAR占用字段總空間,通常總空間是65535字節(jié)
結(jié)論:更大的數(shù)據(jù)還是采用TEXT更好
更大的數(shù)據(jù)類型有LONGTEXT,可以用于選擇
(5)字段設(shè)計的原則
1.盡可能選擇小的數(shù)據(jù)類型,這條無需多說
2.盡可能使用NOT NULL,因為數(shù)據(jù)庫不需要判斷是否為NULL,NULL在MYSQL中的存儲和運(yùn)算更麻煩:
NULL參與常規(guī)運(yùn)算的結(jié)果都是NULL,當(dāng)判斷是否為空的時候,必須采用IS NULL和IS NOT NULL
MYSQL中每條記錄會使用到額外的存儲空間,用于表示每個字段是否為NULL
通常使用一個特殊的數(shù)據(jù)來占位,比如我要表達(dá)NULL通常設(shè)置為空字符串或者0
這種情況又會出現(xiàn)問題,比如成績字段,0代表沒有的話無法區(qū)分0分的學(xué)生,所以可以采用-1,消除歧義
3.字段注釋要完整:gender int comment '性別'
4.單張表的字段數(shù)量不宜過多,通常最多二三十個;數(shù)量過多通常會出現(xiàn)某個業(yè)務(wù)邏輯只是用其中一部分,浪費(fèi)性能
5.預(yù)留字段,比如field1 int field2 varcahr等等;后期項目如果需要更改表結(jié)構(gòu),這樣做會方便很多
(6)關(guān)聯(lián)表的設(shè)計
一對一:一條記錄的字段較多,分布到多個表中存儲
例如學(xué)生表,基礎(chǔ)信息:姓名、身高、班級,還有一些不常用的數(shù)據(jù):籍貫、家庭成員等信息
這時候應(yīng)該設(shè)計基礎(chǔ)信息一張表,不常用數(shù)據(jù)一張表,使用相同的主鍵來表示
一對多:在多的一端使用關(guān)聯(lián)字段,關(guān)聯(lián)一端的主鍵
例如文章和分類表,分類是一端,文章是多端;那么在文章表中需要有一個分類ID的字段做關(guān)聯(lián)
多對多:使用中間表來實(shí)現(xiàn)
例如文章和標(biāo)簽,多對多,那么就需要一張表,字段至少有ID、文章ID、標(biāo)簽ID,每一條記錄代表一個關(guān)聯(lián)
(7)范式
第一范式:字段的原子性,不可再分割
關(guān)系型數(shù)據(jù)庫默認(rèn)滿足第一范式,MYSQL滿足
但也可以強(qiáng)行做:比如一個時間字段,同時寫入開始時間和結(jié)束時間,這就不合理
一個容易出現(xiàn)的問題:(6)中的例子,文檔和標(biāo)簽的設(shè)計中:如果我為了省事,不引入第三張表,而是在文章表中用一個字段標(biāo)簽IDs字段(例如存入1,2,3)
這種情況很常見,是不合理的做法,在更新的時候會出現(xiàn)很多問題,需要把逗號拆開處理,而且無法建索引
除非是類似日志系統(tǒng),存入后不再維護(hù),那么可以使用這種方式
第二范式:滿足第一范式后,消除對主鍵的部分依賴(A字段可以確定B字段,那么B字段依賴A字段)
主鍵:可以唯一標(biāo)識記錄的字段或者字段集合
部分依賴:如果某個字段依賴復(fù)合主鍵的一部分字段,稱之為對主鍵的部分依賴
例如一個課程信息表,字段有:老師,性別,班級,教室,時間,但是不存在ID
這時候需要我們選一個主鍵,這里面每一個字段都不能作為主鍵
老師和班級同時可以作為一個主鍵(復(fù)合主鍵)
但是性別對主鍵是部分依賴,如何消除呢?
部分依賴的產(chǎn)生必須是復(fù)合主鍵,那么增加一個ID即可消除對主鍵的部分依賴
第三范式:第二范式的基礎(chǔ)上,消除對主鍵的傳遞依賴
傳遞依賴:C依賴于B,B依賴于主鍵,那么C對主鍵存在傳遞依賴關(guān)系
上門的例子:性別依賴于老師,老師依賴于ID,那么存在傳遞依賴關(guān)系
消除方式:將獨(dú)立數(shù)據(jù)單獨(dú)建表,使用關(guān)聯(lián)字段進(jìn)行存儲
例子中,建立一個單獨(dú)的表,記錄老師和性別的關(guān)系
總結(jié):獨(dú)立數(shù)據(jù)獨(dú)立建表;表中存在與業(yè)務(wù)邏輯無關(guān)的ID主鍵;表之間的關(guān)系由關(guān)聯(lián)字段(或關(guān)聯(lián)表)進(jìn)行表示
通俗來講:我們建表中,基本都是滿足三大范式的
總結(jié)
以上是生活随笔為你收集整理的mysql字段优化_MySQL优化(1):字段的设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: svn的代码提交到git服务器_svn服
- 下一篇: mysql基本命令总结_mysql 常用