1.為什么要設(shè)置主鍵?
答:在一張表中,可以確定一條唯一記錄的屬性集(這個(gè)屬性集中的元素可能有一個(gè),兩個(gè),三個(gè)甚至更多)稱為超鍵;如果屬性集中只有一個(gè)元素,則通過這個(gè)屬性集就可以確認(rèn)一條唯一的記錄,這樣的屬性集稱為候選鍵;從候選鍵中選擇某一個(gè)屬性集即可作為主鍵。由上述內(nèi)容可知超鍵、候選鍵、主鍵集合包含關(guān)系為:超鍵>候選鍵>主鍵。
但是一張表中可以有主鍵、也可以沒有;但如果是表結(jié)構(gòu)比較復(fù)雜、數(shù)據(jù)量龐大的表,則建議設(shè)置主鍵,否則會(huì)眼中影響CRUD操作的效率,因?yàn)闆]有安全的方法保證值涉及到相關(guān)的行。
2.聚集索引是怎么確定的?
答:如果設(shè)置了主鍵,則InnoDB會(huì)選擇主鍵作為聚集索引,如果不設(shè)主鍵,則會(huì)選擇第一個(gè)NOT NULL的唯一索引作為聚集索引,如果以上兩個(gè)條件都不滿足,則會(huì)選擇長(zhǎng)度為6個(gè)字節(jié)的ROWID作為聚集索引。
3.鍵是用自增還是UUID?
答:首先,InnoDB使用聚集索引,所有的數(shù)據(jù)存儲(chǔ)在主索引的葉子節(jié)點(diǎn)上,這就要求同一葉子節(jié)點(diǎn)(大小為一個(gè)磁盤頁或者內(nèi)存頁)內(nèi)的各條記錄需要按照主鍵順序來存放,因此每當(dāng)有一條數(shù)據(jù)添加進(jìn)數(shù)據(jù)庫(kù)時(shí),MySQL需要根據(jù)其主鍵大小為其查找適當(dāng)?shù)奈恢脕泶娣?,如果頁面達(dá)到裝載因子(15/16),則會(huì)開辟一個(gè)新的節(jié)點(diǎn)來存放。
因此,如果使用自增長(zhǎng)主鍵,那么每次插入新紀(jì)錄時(shí),則只需要把這條記錄添加到當(dāng)前索引節(jié)點(diǎn)的后續(xù)位置;但如果使用UUID作為主鍵,則每次插入新的記錄時(shí),首先需要根據(jù)主鍵的大小在主索引的所有葉子節(jié)點(diǎn)內(nèi)查找合適的位置,然后移動(dòng)查找到的位置之后的記錄,這就造成了移動(dòng)記錄的開銷和空間碎片,后續(xù)需要通過optimize table來優(yōu)化。
所以在使用InnoDB存儲(chǔ)引擎時(shí),如果沒有特別的需要,建議使用與業(yè)務(wù)無關(guān)的自增字段作為主鍵。
4.主鍵為什么不推薦有業(yè)務(wù)含義?
答:歸根結(jié)底,具有業(yè)務(wù)含義的主鍵可能發(fā)生改變,如果發(fā)生改變,則需要根據(jù)主鍵的值在主索引的葉子節(jié)點(diǎn)內(nèi)重新排序,這就可能造成行數(shù)據(jù)的大規(guī)模移動(dòng),帶來很大的時(shí)間開銷,同時(shí),這種變化會(huì)帶來頁分裂,但是在頁分裂的時(shí)候,InnoDB會(huì)在B+索引樹上加鎖,從而導(dǎo)致鎖搶用的現(xiàn)象。
頁分裂:頁分裂發(fā)生在insert(主鍵不遞增)或update操作下,通常來說,B+索引樹的葉子節(jié)點(diǎn)的大小為一個(gè)內(nèi)存頁或者磁盤頁,當(dāng)進(jìn)行上述操作時(shí),會(huì)造成當(dāng)前頁的數(shù)據(jù)大小超出頁大小,這就會(huì)造成需要?jiǎng)?chuàng)建一頁新頁來存放數(shù)據(jù),而這個(gè)新頁則需要根據(jù)頁順序進(jìn)行排列,這就造成:假如原先的頁順序是10-11-12,對(duì)11頁進(jìn)行insert或update操作,數(shù)據(jù)大小超出頁大小,則需要新增一頁來保存,按理來說,新增的一頁頁號(hào)應(yīng)該為12,但是12頁已經(jīng)存在,假設(shè)14頁不存在,創(chuàng)建新頁14,調(diào)整鏈表的前后指針,形成10-11-14-12的頁順序,這樣在物理存儲(chǔ)上頁是混亂的,并且這個(gè)頁很大概率在不同的區(qū)。要調(diào)整這種混亂的頁順序,可以使用optimize table來理順表,另一種就是頁合并。
頁合并:當(dāng)我們?cè)跀?shù)據(jù)庫(kù)中刪除一行記錄時(shí),并不會(huì)立即刪除,而是現(xiàn)在要?jiǎng)h除的行設(shè)置一個(gè)標(biāo)記位,代表該行記錄可被覆蓋,當(dāng)頁中被標(biāo)記的記錄數(shù)量達(dá)到頁大小的50%,則該頁就會(huì)在其相鄰頁尋找是否可以將兩頁合并以優(yōu)化空間,同時(shí)對(duì)記錄更新也可能出現(xiàn)這種情況。
5.貨幣字段存儲(chǔ)用什么類型?
答:貨幣類型推薦使用decimal來存儲(chǔ),因?yàn)槭褂胐ouble和float存儲(chǔ),當(dāng)數(shù)值比較大的時(shí)候,可能存在微小的誤差。
6.時(shí)間字段用什么類型?
答:timestamp(占4個(gè)字節(jié),該字段能存儲(chǔ)的范圍是:1970-01-01 08:00:01至2038-01-19 11:14:07,但是其優(yōu)點(diǎn)是:該字段保存的時(shí)間帶有時(shí)區(qū),一旦系統(tǒng)的時(shí)區(qū)發(fā)生改變,該字段的值就會(huì)自動(dòng)更新,適合用來做跨時(shí)區(qū)的應(yīng)用)
datetime(占8個(gè)字節(jié),該字段的存儲(chǔ)范圍是:1000-01-01 00:00:00至9999-12-31 23:59:59,其缺點(diǎn)是時(shí)間是絕對(duì)的,不會(huì)隨著系統(tǒng)時(shí)區(qū)更新)
bigInt(占8個(gè)字節(jié),存放時(shí)間戳,缺點(diǎn)就是時(shí)間展示不直觀)
7.為什么不在數(shù)據(jù)庫(kù)中存儲(chǔ)文件,視頻,圖片等?
答:數(shù)據(jù)庫(kù)中可以使用text,blob來存儲(chǔ)大文件,但我們通常來說都把文件、視頻存在在文件系統(tǒng)中,而在數(shù)據(jù)庫(kù)中存放存儲(chǔ)路徑,其主要原因是:
(1)MySQL內(nèi)存臨時(shí)表不支持text、blob等類型,處理時(shí)會(huì)非常緩慢。
(2)數(shù)據(jù)庫(kù)大,內(nèi)存占用比較高,維護(hù)麻煩。
(3)binlog太大,如果是主從同步,會(huì)導(dǎo)致主從同步效率問題。文章來源:http://www.zghlxwxcb.cn/news/detail-791550.html
8.如果一張表中如大字段,且該字段不會(huì)頻繁更新,以讀為主,是拆成子表還是存放在一起?
答:如果拆成子表,則會(huì)帶來連表查詢消耗,如果存放在一起,則會(huì)帶來查詢性能,所以視情況而定,但如果數(shù)據(jù)量特別大,建議拆成子表。文章來源地址http://www.zghlxwxcb.cn/news/detail-791550.html
到了這里,關(guān)于數(shù)據(jù)庫(kù)字段設(shè)計(jì)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!