物理机存放mysql实例原则_MySQL优化笔记(四)--表的设计与优化(单表、多表)...
前面講了SQL優(yōu)化以及索引的使用、設(shè)計(jì)優(yōu)化了,那么接下來(lái)就到表的設(shè)計(jì)與優(yōu)化啦!!!真實(shí)地去設(shè)計(jì)優(yōu)化單表結(jié)構(gòu)以及講述多表設(shè)計(jì)基本原則(結(jié)合真實(shí)的生產(chǎn)環(huán)境的取舍來(lái)講述)。
文章結(jié)構(gòu):(1)單表設(shè)計(jì)與優(yōu)化;(2)基于單表設(shè)計(jì)的多表設(shè)計(jì)原則(含表拆分原則);(均以實(shí)際生產(chǎn)開(kāi)發(fā)環(huán)境下的環(huán)境為基準(zhǔn))
文章目錄:
(1)單表設(shè)計(jì)與優(yōu)化
設(shè)計(jì)規(guī)范化表,消除數(shù)據(jù)冗余(以使用正確字段類型最明顯)
- 前三范式
- 所有字段類型
- 所有字段類型羅列
- 針對(duì)常用的varchar,我們來(lái)思考幾個(gè)問(wèn)題
- 給出幾個(gè)類型選取建議
適當(dāng)?shù)娜哂?#xff0c;增加計(jì)算列:(實(shí)際開(kāi)發(fā)中必須思考的點(diǎn))
索引的設(shè)計(jì)
主鍵和外鍵的必要性(實(shí)際項(xiàng)目開(kāi)發(fā)的重要取舍)
存儲(chǔ)過(guò)程、視圖、函數(shù)的適當(dāng)使用(這些是優(yōu)化的方法,這幾個(gè)后面會(huì)講)
傳說(shuō)中的‘三少原則’
分割你的表,減小表尺寸
字段設(shè)計(jì)原則
(2)基于單表設(shè)計(jì)的多表設(shè)計(jì)原則
表關(guān)系
- 一對(duì)一關(guān)系
- 一對(duì)多關(guān)系(多對(duì)一)
- 多對(duì)多關(guān)系
- 注意
- 外鍵與索引
- 建立關(guān)系
分表原則:(涉及分區(qū)分表問(wèn)題探究,以后的篇章再補(bǔ)充實(shí)例)
- 表拆分方式
- 垂直切分
- 水平拆分(分表,分區(qū))–按表中某一字段值的范圍劃分
- 散列庫(kù)表(基于hash算法的切分)
- 在了解完分表了,我們先來(lái)理解區(qū)分分區(qū)與分表吧
- 表拆分建議:(針對(duì)大系統(tǒng))
一、單表設(shè)計(jì)與優(yōu)化:
(1)設(shè)計(jì)規(guī)范化表,消除數(shù)據(jù)冗余(以使用正確字段類型最明顯):
數(shù)據(jù)庫(kù)范式是確保數(shù)據(jù)庫(kù)結(jié)構(gòu)合理,滿足各種查詢需要、避免數(shù)據(jù)庫(kù)操作異常的數(shù)據(jù)庫(kù)設(shè)計(jì)方式。滿足范式要求的表,稱為規(guī)范化表,范式產(chǎn)生于20世紀(jì)70年代初,一般表設(shè)計(jì)滿足前三范式就可以,在這里簡(jiǎn)單介紹一下前三范式。
第一范式(1NF)無(wú)重復(fù)的列
所謂第一范式(1NF)是指在關(guān)系模型中,對(duì)域添加的一個(gè)規(guī)范要求,所有的域都應(yīng)該是原子性的,即數(shù)據(jù)庫(kù)表的每一列都是不可分割的原子數(shù)據(jù)項(xiàng),而不能是集合,數(shù)組,記錄等非原子數(shù)據(jù)項(xiàng)。
第二范式(2NF)屬性
在1NF的基礎(chǔ)上,非碼屬性必須完全依賴于碼[在1NF基礎(chǔ)上消除非主屬性對(duì)主碼的部分函數(shù)依賴]
第三范式(3NF)屬性
在1NF基礎(chǔ)上,任何非主屬性不依賴于其它非主屬性[在2NF基礎(chǔ)上消除傳遞依賴。
通俗點(diǎn)講:
第一范式:屬性(字段)的原子性約束,要求屬性具有原子性,不可再分割;
第二范式:記錄的惟一性約束,要求記錄有惟一標(biāo)識(shí),每條記錄需要有一個(gè)屬性來(lái)做為實(shí)體的唯一標(biāo)識(shí),即每列都要和主鍵相關(guān)。
第三范式:屬性(字段)冗余性的約束,即任何字段不能由其他字段派生出來(lái),在通俗點(diǎn)就是:主鍵沒(méi)有直接關(guān)系的數(shù)據(jù)列必須消除(消除的辦法就是再創(chuàng)建一個(gè)表來(lái)存放他們,當(dāng)然外鍵除外)。即:確保每列都和主鍵列直接相關(guān),而不是間接相關(guān)。
如果數(shù)據(jù)庫(kù)設(shè)計(jì)達(dá)到了完全的標(biāo)準(zhǔn)化,則把所有的表通過(guò)關(guān)鍵字連接在一起時(shí),不會(huì)出現(xiàn)任何數(shù)據(jù)的復(fù)本(repetition)。標(biāo)準(zhǔn)化的優(yōu)點(diǎn)是明顯的,它避免了數(shù)據(jù)冗余,自然就節(jié)省了空間,也對(duì)數(shù)據(jù)的一致性(consistency)提供了根本的保障,杜絕了數(shù)據(jù)不一致的現(xiàn)象,同時(shí)也提高了效率。
尤其是正確字段類型的選擇:(先列出所有字段類型再寫(xiě)建議)
所有字段類型:
(一)整型數(shù)值:
整數(shù)類型
字節(jié)數(shù)
最小值 ~ 最大值
tinyint
1
-128~127 或 0-255
smallint
2
-32768~32767 或 0~65535
mediumint
3
-8388608~8388607 或 0~1677215
int
4
-2147483648~2147483647 或 0~4294967295
bigint
8
-9223372036854775808~9223372036854775807 或 0~18446744073709551615
(二)浮點(diǎn)數(shù)類型
浮點(diǎn)數(shù)類型
字節(jié)數(shù)
最小值 ~ 最大值
double
4
±1.175494351E-38 ~ ± 3.402823466E+38
double
8
±2.2250738585072014E-308 ~ ±1.7976931348623157E+308
(三)定點(diǎn)數(shù)類型
定點(diǎn)數(shù)類型
字節(jié)數(shù)
最小值 ~ 最大值
dec(m,d)
m+2
最大取值范圍與double相同,給定decimal的有效值取值范圍由m和d決定
關(guān)于浮點(diǎn)數(shù)與定點(diǎn)數(shù)有點(diǎn)看法:
浮點(diǎn)數(shù)相對(duì)于定點(diǎn)數(shù)的優(yōu)點(diǎn)是在長(zhǎng)度一定的情況下,浮點(diǎn)數(shù)能夠表示更大的數(shù)據(jù)范圍;它的缺點(diǎn)是會(huì)引起精度問(wèn)題。
使用時(shí)我們要注意:
1. 浮點(diǎn)數(shù)存在誤差問(wèn)題;
2. 對(duì)貨幣等對(duì)精度敏感的數(shù)據(jù),應(yīng)該用定點(diǎn)數(shù)表示或存儲(chǔ);
3. 編程中,如果用到浮點(diǎn)數(shù),要特別注意誤差問(wèn)題,并盡量避免做浮點(diǎn)數(shù)比較;
4. 要注意浮點(diǎn)數(shù)中一些特殊值的處理。
(四)位類型
位類型
字節(jié)數(shù)
最小值 ~ 最大值
bit(m)
1~8
bit(1) ~ bit(64)
(五)日期時(shí)間類型
時(shí)間日期類型
字節(jié)數(shù)
最小值 ~ 最大值
date
4
1000-01-01 ~ 9999-12-31
datetime
8
1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
timestamp
4
19700101080001 ~ 2038年某個(gè)時(shí)刻
time
3
-838:59:59 ~ 838:59:59
year
1
1901 ~ 2155
mysql中用now()寫(xiě)入當(dāng)前時(shí)間。
(六)字符串類型:
字符串類型
字節(jié)數(shù)
取值范圍
char(m)
m
m為0 ~ 255之間的整數(shù)
varchar(m)
值長(zhǎng)度+1
m為0~65535之間的整數(shù)
tinytext
值長(zhǎng)度+2
允許長(zhǎng)度0~255字節(jié)
text
值長(zhǎng)度+2
允許長(zhǎng)度0~65535字節(jié)
mediumtext
值長(zhǎng)度+3
允許長(zhǎng)度0~167772150字節(jié)
longtext
值長(zhǎng)度+3
允許長(zhǎng)度0~4294967295字節(jié)
binary(m)
m
允許0~m個(gè)字節(jié)定長(zhǎng)的字符串
varbinary(m)
值長(zhǎng)度+1
允許0~m個(gè)字節(jié)變長(zhǎng)的字符串
tinyblob
值長(zhǎng)度+1
允許長(zhǎng)度0~255字節(jié)
blob
值長(zhǎng)度+2
允許長(zhǎng)度0~65535字節(jié)
mediumblob
值長(zhǎng)度+3
允許長(zhǎng)度0~167772150字節(jié)
longblob
值長(zhǎng)度+4
允許長(zhǎng)度0~4294967295字節(jié)
enum
1或2
1255個(gè)成員需要1個(gè)字節(jié)存;25565535個(gè)成員,2個(gè)字節(jié)存
set
1/2/3/4/8
類似enum,set一次可以選取多個(gè)成員,而enum只能一個(gè)
針對(duì)常用的varchar,我們來(lái)思考幾個(gè)問(wèn)題:
1)varchar的長(zhǎng)度?
MySQL的文檔,其中對(duì)varchar字段類型這樣描述:varchar(m) 變長(zhǎng)字符串。m 表示最大列長(zhǎng)度。m的范圍是0到65,535。(VARCHAR的最大實(shí)際長(zhǎng)度由最長(zhǎng)的行的大小和使用的字符集確定,最大有效長(zhǎng)度是65,532字節(jié))。
mysql varchar(50) 不管中文 還是英文 都是存50個(gè)的,但是一個(gè)表中所有varchar字段的總長(zhǎng)度跟編碼有關(guān),如果是utf-8,那么大概65535/3,如果是gbk,那么大概65535/2.
2)存儲(chǔ)限制?編碼長(zhǎng)度限制?行長(zhǎng)度限制?超出了,會(huì)變成怎樣?
針對(duì)第一個(gè)問(wèn)題:varchar 字段是將實(shí)際內(nèi)容單獨(dú)存儲(chǔ)在聚簇索引之外,實(shí)際存儲(chǔ)從第二個(gè)字節(jié)開(kāi)始,接著要用1到2個(gè)字節(jié)表示實(shí)際長(zhǎng)度(長(zhǎng)度超過(guò)255時(shí)需要2個(gè)字節(jié)),因此最大長(zhǎng)度不能超過(guò)65535。
針對(duì)第二個(gè)問(wèn)題:字符類型若為gbk,每個(gè)字符最多占2個(gè)字節(jié)。字符類型若為utf8,每個(gè)字符最多占3個(gè)字節(jié)。
針對(duì)第三個(gè)問(wèn)題:導(dǎo)致實(shí)際應(yīng)用中varchar長(zhǎng)度限制的是一個(gè)行定義的長(zhǎng)度。 MySQL要求一個(gè)行的定義長(zhǎng)度不能超過(guò)65535。若定義的表長(zhǎng)度超過(guò)這個(gè)值,則提示
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs。
針對(duì)第四個(gè)問(wèn)題:若定義的時(shí)候超過(guò)上述限制,則varchar字段會(huì)被強(qiáng)行轉(zhuǎn)為text類型,并產(chǎn)生warning。
3)與char的對(duì)比:
CHAR(M)定義的列的長(zhǎng)度為固定的,M取值可以為0~255之間,當(dāng)保存CHAR值時(shí),在它們的右邊填充空格以達(dá)到指定的長(zhǎng)度。當(dāng)檢 索到CHAR值時(shí),尾部的空格被刪除掉。在存儲(chǔ)或檢索過(guò)程中不進(jìn)行大小寫(xiě)轉(zhuǎn)換。CHAR存儲(chǔ)定長(zhǎng)數(shù)據(jù)很方便,CHAR字段上的索引效率級(jí)高,比如定義 char(10),那么不論你存儲(chǔ)的數(shù)據(jù)是否達(dá)到了10個(gè)字節(jié),都要占去10個(gè)字節(jié)的空間,不足的自動(dòng)用空格填充。
CHAR和VARCHAR最大的不同就是一個(gè)是固定長(zhǎng)度,一個(gè)是可變長(zhǎng)度。由于是可變長(zhǎng)度,因此實(shí)際存儲(chǔ)的時(shí)候是實(shí)際字符串再加上一個(gè)記錄 字符串長(zhǎng)度的字節(jié)(如果超過(guò)255則需要兩個(gè)字節(jié))。如果分配給CHAR或VARCHAR列的值超過(guò)列的最大長(zhǎng)度,則對(duì)值進(jìn)行裁剪以使其適合。如果被裁掉 的字符不是空格,則會(huì)產(chǎn)生一條警告。如果裁剪非空格字符,則會(huì)造成錯(cuò)誤(而不是警告)并通過(guò)使用嚴(yán)格SQL模式禁用值的插入。
4)char、varchar與text的建議:
TEXT只能儲(chǔ)存純文本文件。
效率來(lái)說(shuō)基本是char>varchar>text,但是如果使用的是Innodb引擎的話,推薦使用varchar代替char
char和varchar可以有默認(rèn)值,text不能指定默認(rèn)值
以下給出幾個(gè)類型選取建議
(一)數(shù)字類型:
1)不到不要使用DOUBLE,不僅僅只是存儲(chǔ)長(zhǎng)度的問(wèn)題,同時(shí)還會(huì)存在精確性的問(wèn)題。
2)固定精度的小數(shù),也不建議使用DECIMAL,建議乘以固定倍數(shù)轉(zhuǎn)換成整數(shù)存儲(chǔ),可以大大節(jié)省存儲(chǔ)空間,且不會(huì)帶來(lái)任何附加維護(hù)成本。
3)對(duì)于整數(shù)的存儲(chǔ),在數(shù)據(jù)量較大的情況下,建議區(qū)分開(kāi) TINYINT / INT / BIGINT 的選擇,因?yàn)槿咚加玫拇鎯?chǔ)空間也有很大的差別,能確定不會(huì)使用負(fù)數(shù)的字段,建議添加unsigned定義。當(dāng)然,如果數(shù)據(jù)量較小的數(shù)據(jù)庫(kù),也可以不用嚴(yán)格區(qū)分三個(gè)整數(shù)類型。
4)對(duì)于整型數(shù)值,mysql支持在類型名稱后面的小括號(hào)內(nèi)指定顯示寬度,例如int(5)表示當(dāng)數(shù)值寬度小于5位時(shí)候在數(shù)值前面填滿寬度,一般配合zerofill屬性使用。如果一個(gè)列指定為zerofill,則MySQL自動(dòng)為該列添加unsigned屬性。
5)在數(shù)據(jù)量較大時(shí)、建議把實(shí)數(shù)類型轉(zhuǎn)為整數(shù)類型。原因很簡(jiǎn)單:1. 浮點(diǎn)不精確;2.定點(diǎn)計(jì)算代價(jià)昂貴。例如:要存放財(cái)務(wù)數(shù)據(jù)精確到萬(wàn)分之一、則可以把所有金額乘以一百萬(wàn)、然后存在BIGINT下。
(二)字符類型:
1)盡量不要使用 TEXT 數(shù)據(jù)類型,其處理方式?jīng)Q定了他的性能要低于char或者是varchar類型的處理。定長(zhǎng)字段,建議使用 CHAR 類型,不定長(zhǎng)字段盡量使用 VARCHAR,且僅僅設(shè)定適當(dāng)?shù)淖畲箝L(zhǎng)度,而不是非常隨意的給一個(gè)很大的最大長(zhǎng)度限定,因?yàn)椴煌拈L(zhǎng)度范圍,MySQL也會(huì)有不一樣的存儲(chǔ)處理。
2)char會(huì)刪除字符串尾部的空格,varchar不會(huì),varchar向前補(bǔ)1-2字節(jié);char定長(zhǎng)。binary類似于char,binary只能保存二進(jìn)制字符串。
char是固定長(zhǎng)度,所以它的處理速度比varchar快得多,但缺點(diǎn)是浪費(fèi)存儲(chǔ)空間,不能在行尾保存空格。在MySQL中,MyISAM建議使用固定長(zhǎng)度代替可變長(zhǎng)度列;InnoDB建議使用varchar類型,因?yàn)樵贗nnoDB中,內(nèi)部行存儲(chǔ)格式?jīng)]有區(qū)分固定長(zhǎng)度和可變長(zhǎng)度。
3)enum類型忽略大小寫(xiě)。
4)text與blob區(qū)別:blob保存二進(jìn)制數(shù)據(jù);text保存字符數(shù)據(jù),有字符集。text和blob不能有默認(rèn)值。
應(yīng)用:text與blob主要區(qū)別是text用來(lái)保存字符數(shù)據(jù)(如文章,日記等),blob用來(lái)保存二進(jìn)制數(shù)據(jù)(如照片等)。blob與text在執(zhí)行了大量刪除操作時(shí)候,有性能問(wèn)題(產(chǎn)生大量的“空洞“),為提高性能建議定期optimize table 對(duì)這類表進(jìn)行碎片整理。
關(guān)于text與blob我們有些看法建議:
1. BLOB和TEXT值也會(huì)引起自己的一些問(wèn)題,特別是執(zhí)行了大量的刪除或更新操作的時(shí)候。刪除這種值會(huì)在數(shù)據(jù)表中留下很大的"空洞",以后填入這些"空洞"的記錄可能長(zhǎng)度不同,為了提高性能,建議定期使用 OPTIMIZE TABLE 功能對(duì)這類表進(jìn)行碎片整理.
2. 在不必要的時(shí)候避免檢索大型的BLOB或TEXT值。
3. 把BLOB或TEXT列分離到單獨(dú)的表中。在某些環(huán)境中,如果把這些數(shù)據(jù)列移動(dòng)到第二張數(shù)據(jù)表中,可以讓你把原數(shù)據(jù)表中 的數(shù)據(jù)列轉(zhuǎn)換為固定長(zhǎng)度的數(shù)據(jù)行格式,那么它就是有意義的。這會(huì)減少主表中的碎片,使你得到固定長(zhǎng)度數(shù)據(jù)行的性能優(yōu)勢(shì)。它還使你在主數(shù)據(jù)表上運(yùn)行 SELECT *查詢的時(shí)候不會(huì)通過(guò)網(wǎng)絡(luò)傳輸大量的BLOB或TEXT值。
(三)時(shí)間類型:
1)盡量使用TIMESTAMP類型,因?yàn)槠浯鎯?chǔ)空間只需要 DATETIME 類型的一半。對(duì)于只需要精確到某一天的數(shù)據(jù)類型,建議使用DATE類型,因?yàn)樗拇鎯?chǔ)空間只需要3個(gè)字節(jié),比TIMESTAMP還少。不建議通過(guò)INT類型類存儲(chǔ)一個(gè)unix timestamp 的值,因?yàn)檫@太不直觀,會(huì)給維護(hù)帶來(lái)不必要的麻煩,同時(shí)還不會(huì)帶來(lái)任何好處。
2)根據(jù)實(shí)際需要選擇能夠滿足應(yīng)用的最小存儲(chǔ)日期類型。
3)timestamp,日期類型中只有它能夠和實(shí)際時(shí)區(qū)相對(duì)應(yīng)。
(四)ENUM & SET:
對(duì)于狀態(tài)字段,可以嘗試使用 ENUM 來(lái)存放,因?yàn)榭梢詷O大的降低存儲(chǔ)空間,而且即使需要增加新的類型,只要增加于末尾,修改結(jié)構(gòu)也不需要重建表數(shù)據(jù)。如果是存放可預(yù)先定義的屬性數(shù)據(jù)呢?可以嘗試使用SET類型,即使存在多種屬性,同樣可以游刃有余,同時(shí)還可以節(jié)省不小的存儲(chǔ)空間。
(五)LOB類型:
強(qiáng)烈反對(duì)在數(shù)據(jù)庫(kù)中存放 LOB 類型數(shù)據(jù),雖然數(shù)據(jù)庫(kù)提供了這樣的功能,但這不是他所擅長(zhǎng)的,我們更應(yīng)該讓合適的工具做他擅長(zhǎng)的事情,才能將其發(fā)揮到極致。
(2)適當(dāng)?shù)娜哂?#xff0c;增加計(jì)算列:(實(shí)際開(kāi)發(fā)中必須思考的點(diǎn))
數(shù)據(jù)庫(kù)設(shè)計(jì)的實(shí)用原則是:在數(shù)據(jù)冗余和處理速度之間找到合適的平衡點(diǎn)。
滿足范式的表一定是規(guī)范化的表,但不一定是最佳的設(shè)計(jì)。很多情況下會(huì)為了提高數(shù)據(jù)庫(kù)的運(yùn)行效率,常常需要降低范式標(biāo)準(zhǔn):適當(dāng)增加冗余,達(dá)到以空間換時(shí)間的目的。比如我們有一個(gè)表,產(chǎn)品名稱,單價(jià),庫(kù)存量,總價(jià)值。這個(gè)表是不滿足第三范式的,因?yàn)椤翱們r(jià)值”可以由“單價(jià)”乘以“數(shù)量”得到,說(shuō)明“金額”是冗余字段。但是,增加“總價(jià)值”這個(gè)冗余字段,可以提高查詢統(tǒng)計(jì)的速度,這就是以空間換時(shí)間的作法。合理的冗余可以分散數(shù)據(jù)量大的表的并發(fā)壓力,也可以加快特殊查詢的速度,冗余字段可以有效減少數(shù)據(jù)庫(kù)表的連接,提高效率。
其中"總價(jià)值"就是一個(gè)計(jì)算列,在數(shù)據(jù)庫(kù)中有兩種類型:數(shù)據(jù)列和計(jì)算列,數(shù)據(jù)列就是需要我們手動(dòng)或者程序給予賦值的列,計(jì)算列是源于表中其他的數(shù)據(jù)計(jì)算得來(lái),比如這里的"總價(jià)值"
在SQL中創(chuàng)建計(jì)算列:
create table goods(
id int auto_increment not null,
c1 int,
c2 int,
c3 int as (c1+c2), //這個(gè)就是計(jì)算列啦
primary key(id)
)
(3)索引的設(shè)計(jì):
表優(yōu)化的重要途徑,百萬(wàn)級(jí)別的表沒(méi)有索引,注定卡死。
(4)主鍵和外鍵的必要性(實(shí)際項(xiàng)目開(kāi)發(fā)的重要取舍)
概述:主鍵與外鍵的設(shè)計(jì),在全局?jǐn)?shù)據(jù)庫(kù)的設(shè)計(jì)中,占有重要地位。 因?yàn)?#xff1a;主鍵是實(shí)體的抽象,主鍵與外鍵的配對(duì),表示實(shí)體之間的連接。
主鍵:根據(jù)第二范式,需要有一個(gè)字段去標(biāo)識(shí)這條記錄,主鍵無(wú)疑是最好的標(biāo)識(shí),但是很多表也不一定需要主鍵,但是對(duì)于數(shù)據(jù)量大,查詢頻繁的數(shù)據(jù)庫(kù)表,一定要有主鍵,主鍵可以增加效率、防止重復(fù)等優(yōu)點(diǎn)。
主鍵的選擇也比較重要,一般選擇總的長(zhǎng)度小的鍵,小的鍵的比較速度快,同時(shí)小的鍵可以使主鍵的B樹(shù)結(jié)構(gòu)的層次更少。
主鍵的選擇還要注意組合主鍵的字段次序,對(duì)于組合主鍵來(lái)說(shuō),不同的字段次序的主鍵的性能差別可能會(huì)很大,一般應(yīng)該選擇重復(fù)率低、單獨(dú)或者組合查詢可能性大的字段放在前面。
外鍵:外鍵作為數(shù)據(jù)庫(kù)對(duì)象,很多人認(rèn)為麻煩而不用,實(shí)際上,外鍵在大部分情況下是很有用的,理由是:外鍵是最高效的一致性維護(hù)方法。
數(shù)據(jù)庫(kù)的一致性要求,依次可以用外鍵、CHECK約束、規(guī)則約束、觸發(fā)器、客戶端程序,一般認(rèn)為,離數(shù)據(jù)越近的方法效率越高。但是!!!要謹(jǐn)慎使用級(jí)聯(lián)刪除和級(jí)聯(lián)更新,因?yàn)榧?jí)聯(lián)刪除和級(jí)聯(lián)更新有些突破了傳統(tǒng)的關(guān)于外鍵的定義,功能有點(diǎn)太過(guò)強(qiáng)大,使用前必須確定自己已經(jīng)把握好其功能范圍,否則,級(jí)聯(lián)刪除和級(jí)聯(lián)更新可能讓你的數(shù)據(jù)莫名其妙的被修改或者丟失。從性能看級(jí)聯(lián)刪除和級(jí)聯(lián)更新是比其他方法更高效的方法。
實(shí)際項(xiàng)目中的主外鍵取舍設(shè)計(jì):(在性能和可擴(kuò)展性之間尋求平衡)
邊緣模塊指的是小功能不常用需求很少再改的模塊;中心模塊是指關(guān)聯(lián)的東西太多的模塊、是很多表的主表;物理鍵指的是在表建立主外鍵關(guān)聯(lián),邏輯主外鍵指的是利用字段去實(shí)現(xiàn)邏輯主外鍵關(guān)聯(lián);熱點(diǎn)模塊指的是需求經(jīng)常要改的模塊
大型系統(tǒng):
1. 針對(duì)性能要求不高,安全要求高的模塊,推薦使用物理主外鍵關(guān)聯(lián);針對(duì)性能要求高、安全自己控制的模塊,推薦不用物理外鍵;
2. 針對(duì)中心模塊和其他模塊的聯(lián)系,推薦使用物理主外鍵。
3. 針對(duì)熱點(diǎn)模塊,必須使用邏輯主外鍵
4. 針對(duì)邊緣模塊,推薦使用物理主外鍵
小系統(tǒng)??
隨便你啦,也就是20張表以下的系統(tǒng)。邏輯不復(fù)雜都無(wú)所謂啦,不過(guò)推薦還是使用外鍵。
注意:
不用外鍵而用程序控制數(shù)據(jù)一致性和完整性時(shí),應(yīng)該寫(xiě)一層來(lái)保證,然后個(gè)個(gè)應(yīng)用通過(guò)這個(gè)層來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。
外鍵是有性能問(wèn)題的,不能過(guò)分追求。
(5)存儲(chǔ)過(guò)程、視圖、函數(shù)的適當(dāng)使用(這些是優(yōu)化的方法,這幾個(gè)后面會(huì)講):
很多人習(xí)慣將復(fù)雜操作都放在應(yīng)用程序?qū)?#xff0c;但如果你要優(yōu)化數(shù)據(jù)訪問(wèn)性能,將SQL代碼移植到數(shù)據(jù)庫(kù)上(使用存儲(chǔ)過(guò)程,視圖,函數(shù)和觸發(fā)器)也是一個(gè)很大的改進(jìn)原因如下:
1)存儲(chǔ)過(guò)程減少了網(wǎng)絡(luò)傳輸、處理及存儲(chǔ)的工作量,且經(jīng)過(guò)編譯和優(yōu)化,執(zhí)行速度快,易于維護(hù),且表的結(jié)構(gòu)改變時(shí),不影響客戶端的應(yīng)用程序
2)使用存儲(chǔ)過(guò)程,視圖,函數(shù)有助于減少應(yīng)用程序中SQL復(fù)制的弊端,因?yàn)楝F(xiàn)在只在一個(gè)地方集中處理SQL
3)使用數(shù)據(jù)庫(kù)對(duì)象實(shí)現(xiàn)所有的TSQL有助于分析TSQL的性能問(wèn)題,同時(shí)有助于你集中管理TSQL代碼,更好的重構(gòu)TSQL代碼。
(6)傳說(shuō)中的‘三少原則’:
1)數(shù)據(jù)庫(kù)的表越少越好
2)表的字段越少越好
3)字段中的組合主鍵、組合索引越少越好
這里的少是相對(duì)的,是減少數(shù)據(jù)冗余的重要設(shè)計(jì)理念而已。
實(shí)際上,我們?yōu)榱藴p少單表查詢壓力,會(huì)把去分表,從而分發(fā)記錄量,避免一個(gè)超級(jí)表的誕生。
(7)分割你的表,減小表尺寸
如果你發(fā)現(xiàn)某個(gè)表的記錄太多,例如超過(guò)一千萬(wàn)條,則要對(duì)該表進(jìn)行水平分割。水平分割的做法是,以該表主鍵的某個(gè)值為界線,將該表的記錄水平分割為兩個(gè)表。
如果你若發(fā)現(xiàn)某個(gè)表的字段太多,例如超過(guò)八十個(gè),則垂直分割該表,將原來(lái)的一個(gè)表分解為兩個(gè)表
(8)字段設(shè)計(jì)原則:
字段是數(shù)據(jù)庫(kù)最基本的單位,其設(shè)計(jì)對(duì)性能的影響是很大的。需要注意如下:
1)數(shù)據(jù)類型盡量用數(shù)字型,數(shù)字型的比較比字符型的快很多。
2)數(shù)據(jù)類型盡量小,這里的盡量小是指在滿足可以預(yù)見(jiàn)的未來(lái)需求的前提下的。
3)盡量不要允許NULL,除非必要,可以用NOT NULL+DEFAULT代替。
NULL 類型比較特殊,SQL 難優(yōu)化。雖然 MySQL NULL類型和 Oracle 的NULL 有差異,會(huì)進(jìn)入索引中,但如果是一個(gè)組合索引,那么這個(gè)NULL 類型的字段會(huì)極大影響整個(gè)索引的效率。此外,NULL 在索引中的處理也是特殊的,也會(huì)占用額外的存放空間。
4)少用TEXT和IMAGE,二進(jìn)制字段的讀寫(xiě)是比較慢的,而且,讀取的方法也不多,大部分情況下最好不用。
5)自增字段要慎用,不利于數(shù)據(jù)遷移
二、基于單表設(shè)計(jì)的多表設(shè)計(jì)原則:
(1)表關(guān)系:
一)一對(duì)一關(guān)系:
定義:
在這種關(guān)系中,關(guān)系表的每一邊都只能存在一個(gè)記錄。每個(gè)數(shù)據(jù)表中的關(guān)鍵字在對(duì)應(yīng)的關(guān)系表中只能存在一個(gè)記錄或者沒(méi)有對(duì)應(yīng)的記錄。這種關(guān)系和一對(duì)配偶之間的關(guān)系非常相似——要么你已經(jīng)結(jié)婚,你和你的配偶只能有一個(gè)配偶,要么你沒(méi)有結(jié)婚沒(méi)有配偶。大多數(shù)的一對(duì)一的關(guān)系都是某種商業(yè)規(guī)則約束的結(jié)果,而不是按照數(shù)據(jù)的自然屬性來(lái)得到的。如果沒(méi)有這些規(guī)則的約束,你通常可以把兩個(gè)數(shù)據(jù)表合并進(jìn)一個(gè)數(shù)據(jù)表,而且不會(huì)打破任何規(guī)范化的規(guī)則。
一對(duì)一關(guān)系又分為:一對(duì)一外鍵關(guān)聯(lián)和一對(duì)一主鍵關(guān)聯(lián)。
一對(duì)一主鍵關(guān)聯(lián):要求兩個(gè)表的主鍵必須完全一致,通過(guò)兩個(gè)表的主鍵建立關(guān)聯(lián)關(guān)系。
可以看到下圖,很明顯的,班級(jí)編號(hào)作為主鍵的話,就是一個(gè)主鍵關(guān)聯(lián)了。
這里寫(xiě)圖片描述
一對(duì)一外鍵關(guān)聯(lián):
下面又很明顯看到,以班主任ID作為外鍵關(guān)聯(lián)起來(lái)的一個(gè)表。
這里寫(xiě)圖片描述
二)一對(duì)多關(guān)系(多對(duì)一):
定義:
主鍵數(shù)據(jù)表中只能含有一個(gè)記錄,而在其關(guān)系表中這條記錄可以與一個(gè)或者多個(gè)記錄相關(guān),也可以沒(méi)有記錄與之相關(guān)。這種關(guān)系類似于你和你的父母之間的關(guān)系。你只有一位母親,但是你母親可以有幾個(gè)孩子。
下圖可以看到:一對(duì)多-班級(jí)表有多個(gè)學(xué)生;多對(duì)一-多個(gè)學(xué)生屬于一個(gè)班級(jí)。
這里寫(xiě)圖片描述
三)多對(duì)多關(guān)系:
定義:
兩個(gè)數(shù)據(jù)表里的每條記錄都可以和另一個(gè)數(shù)據(jù)表里任意數(shù)量的記錄(或者沒(méi)有記錄)相關(guān)。例如,如果你有多個(gè)兄弟姐妹,這對(duì)你的兄弟姐妹也是一樣(有多個(gè)兄弟姐妹),多對(duì)多這種關(guān)系需要引入第三個(gè)數(shù)據(jù)表,這種數(shù)據(jù)表稱為聯(lián)系表或者連接表,因?yàn)殛P(guān)系型系統(tǒng)不能直接實(shí)現(xiàn)這種關(guān)系。
在RDBMS中,必須使用中間表來(lái)表示多對(duì)多的關(guān)系。中間表我們可以分成兩種,一種是純粹表示關(guān)系的中間表,一種是表示中間實(shí)體的中間表。
純粹表示關(guān)系的中間表很簡(jiǎn)單,只需要兩列:AID和BID,AID以外鍵關(guān)聯(lián)到A表的主鍵,BID以外鍵關(guān)聯(lián)到B表的主鍵,然后這兩個(gè)列組成聯(lián)合主鍵。這個(gè)中間表純粹是表示多對(duì)多關(guān)系而存在,在業(yè)務(wù)上不會(huì)有對(duì)應(yīng)的實(shí)體與之對(duì)應(yīng)。比如前面提到的學(xué)生和課程的關(guān)系,如果我們只需要知道哪些學(xué)生上哪些課,哪些課有哪些學(xué)生選,不需要有更多的信息的情況下,我們就可以建立“學(xué)生課程”中間表,里面只有學(xué)生ID和課程ID兩個(gè)字段。
這里寫(xiě)圖片描述
中間實(shí)體是在純粹的中間關(guān)系表的基礎(chǔ)上,加上了更多的屬性,從而形成了一個(gè)新的實(shí)體。比如上面提到的學(xué)生和課程的關(guān)系,如果我們需要記錄學(xué)生選課的時(shí)間、學(xué)生選擇這門課程后的考試成績(jī),那么我們就像建立一個(gè)“選課”實(shí)體,該實(shí)體具有如下屬性:
選課ID,主鍵
學(xué)生ID,與學(xué)生表做外鍵關(guān)聯(lián)
課程ID,與課程表做外鍵關(guān)聯(lián)
選課時(shí)間,DateTime類型
考試成績(jī),記錄選修該課程后考試的最終成績(jī)
注意:
一)外鍵與索引:
外鍵是一種約束,與索引的概念不一樣,只是大多數(shù)情況下,我們建立外鍵時(shí),都會(huì)在外鍵列上建立對(duì)應(yīng)的索引。外鍵的存在會(huì)在每一次數(shù)據(jù)插入、修改時(shí)進(jìn)行約束檢查,如果不滿足外鍵約束,則禁止數(shù)據(jù)的插入或修改,這必然帶來(lái)一個(gè)問(wèn)題,就是在數(shù)據(jù)量特別大的情況下,每一次約束檢查必然導(dǎo)致性能的下降。索引其實(shí)也有類似的問(wèn)題,索引如果建多了,那么在插入刪除修改數(shù)據(jù)時(shí)也要去維護(hù)對(duì)應(yīng)的索引,所以索引的存在也會(huì)導(dǎo)致數(shù)據(jù)操作變慢。
不過(guò)外鍵與索引的優(yōu)點(diǎn)不同,外鍵只是保證數(shù)據(jù)的一致性,并不能給系統(tǒng)性能帶來(lái)任何好處,所以由于外鍵導(dǎo)致的插入數(shù)據(jù)變慢會(huì)隨著數(shù)據(jù)量的增長(zhǎng)而越來(lái)越嚴(yán)重。而索引的目的是為了檢索數(shù)據(jù)更快,維護(hù)數(shù)據(jù)時(shí)導(dǎo)致的索引數(shù)據(jù)的變更,對(duì)性能的影響不會(huì)像外鍵那樣隨著數(shù)據(jù)量增長(zhǎng)而變得嚴(yán)重(當(dāng)然大數(shù)量時(shí)的索引樹(shù)維護(hù)會(huì)比小數(shù)據(jù)量的索引樹(shù)維護(hù)更麻煩,但至少不是像外鍵那樣)。
出于性能的考慮,如果我們的系統(tǒng)完全由我們開(kāi)發(fā)的程序使用,而不需要提供數(shù)據(jù)庫(kù)給其他應(yīng)用系統(tǒng)寫(xiě)入數(shù)據(jù),而且對(duì)性能要求較高,那么我們可以考慮在生產(chǎn)環(huán)境中不使用外鍵,只需要建立能夠提高性能的索引。由于整個(gè)數(shù)據(jù)庫(kù)的操作都是由我們開(kāi)發(fā)的程序來(lái)完成的,所以我們程序可以在開(kāi)發(fā)過(guò)程中做好各方面的一致性檢查,保證操作的數(shù)據(jù)是滿足外鍵約束的,而不需要真正的存在這樣一個(gè)外鍵約束。怎么做到這一點(diǎn)呢,首先,我們?cè)诮?shù)據(jù)庫(kù)時(shí)有多個(gè)腳本,包括創(chuàng)建表、創(chuàng)建初始化數(shù)據(jù)、創(chuàng)建索引、創(chuàng)建外鍵等,我們?cè)陂_(kāi)發(fā)和測(cè)試環(huán)境中,都把這些腳本運(yùn)行了,以使開(kāi)發(fā)測(cè)試環(huán)境中的數(shù)據(jù)庫(kù)是完整的,經(jīng)過(guò)大量測(cè)試保證應(yīng)用程序能夠維護(hù)數(shù)據(jù)之間的約束的情況下,那么我們?cè)谏a(chǎn)時(shí),并不需要運(yùn)行創(chuàng)建外鍵這個(gè)腳本文件,只需要?jiǎng)?chuàng)建表、初始化數(shù)據(jù)、創(chuàng)建索引等即可。
二)建立關(guān)系
在開(kāi)始著手考慮建立關(guān)系表之間的關(guān)系之前,你可能需要對(duì)數(shù)據(jù)非常熟悉。只有在熟悉數(shù)據(jù)之后,關(guān)聯(lián)會(huì)比你剛開(kāi)始的時(shí)候更明顯。你的數(shù)據(jù)庫(kù)系統(tǒng)依賴于在兩個(gè)數(shù)據(jù)表中找到的匹配值來(lái)建立關(guān)系。
進(jìn)行匹配的值都是主鍵和外鍵的值。(關(guān)系模型不要求一個(gè)關(guān)系必須對(duì)應(yīng)的使用一個(gè)主鍵來(lái)確定。你可以使用數(shù)據(jù)表中的任何備選關(guān)鍵字來(lái)建立關(guān)系,但是使用主鍵是大家都已經(jīng)接受的標(biāo)準(zhǔn)。)主鍵(primary key)唯一的識(shí)別表中的每個(gè)記錄。而外鍵(foreign key)只是簡(jiǎn)單的將一個(gè)數(shù)據(jù)表中的主鍵存放在另外一個(gè)數(shù)據(jù)表中。同樣地,對(duì)于你來(lái)說(shuō)也不需要做太多的工作——只是簡(jiǎn)單地將主鍵加到關(guān)系表中,并將其定義為外鍵。
(2)分表原則:(涉及分區(qū)分表問(wèn)題探究,以后的篇章再補(bǔ)充實(shí)例)
分表主要目的是為突破單節(jié)點(diǎn)數(shù)據(jù)庫(kù)服務(wù)器的 I/O 能力限制,解決數(shù)據(jù)庫(kù)擴(kuò)展性問(wèn)題。 同時(shí)分表分庫(kù)等思想也將引出以后的數(shù)據(jù)庫(kù)集群,主從復(fù)制、讀寫(xiě)分離方案.....
為什么我們要分表分區(qū)???
日常開(kāi)發(fā)中我們經(jīng)常會(huì)遇到大表的情況,所謂的大表是指存儲(chǔ)了百萬(wàn)級(jí)乃至千萬(wàn)級(jí)條記錄的表。這樣的表過(guò)于龐大,導(dǎo)致數(shù)據(jù)庫(kù)在查詢和插入的時(shí)候耗時(shí)太長(zhǎng),性能低下,如果涉及聯(lián)合查詢的情況,性能會(huì)更加糟糕。分表和表分區(qū)的目的就是減少數(shù)據(jù)庫(kù)的負(fù)擔(dān),提高數(shù)據(jù)庫(kù)的效率,通常點(diǎn)來(lái)講就是提高表的增刪改查效率。
(一)表拆分方式:
1)垂直切分:
這里寫(xiě)圖片描述
定義:
把主鍵和一些數(shù)據(jù)表的列放在一個(gè)表中,然后把主鍵和另一些數(shù)據(jù)表的列放在一個(gè)表中。
如果一個(gè)表的某些列常用,另一些不常用,則可以采用垂直拆分。垂直拆分可以使數(shù)據(jù)行變小,一個(gè)數(shù)據(jù)頁(yè)就可以存放更多的數(shù)據(jù),在查詢時(shí)候可以減少I/O次數(shù)。其缺點(diǎn)是需要管理冗余列,查詢所有數(shù)據(jù)時(shí)候需要join查找。
優(yōu)點(diǎn):
使得行數(shù)據(jù)變小,一個(gè)數(shù)據(jù)塊(Block)就能存放更多的數(shù)據(jù),在查詢時(shí)就會(huì)減少I/O次數(shù)(每次查詢時(shí)讀取的Block 就少)。
可以達(dá)到最大化利用Cache的目的。
缺點(diǎn):
表垂直分割后,主碼(主鍵)出現(xiàn)冗余,需要管理冗余列
會(huì)引起表連接JOIN操作(增加CPU開(kāi)銷)需要從業(yè)務(wù)上規(guī)避
2)水平拆分(分表,分區(qū))--按表中某一字段值的范圍劃分:
這里寫(xiě)圖片描述
定義:
根據(jù)列的范圍值進(jìn)行合理切分,放在多個(gè)獨(dú)立的表或分區(qū)中。
適用場(chǎng)景:
表很大,分割后可以降低查詢時(shí)候需要讀取的數(shù)據(jù)和索引的頁(yè)數(shù),同時(shí)降低索引的層數(shù),提高查詢速度。
表中的數(shù)據(jù)是獨(dú)立的,例如表中分別記錄各個(gè)地區(qū)的數(shù)據(jù)或不同時(shí)期的數(shù)據(jù),特別是有些數(shù)據(jù)常用,而另一些數(shù)據(jù)不常用。
需要把數(shù)據(jù)放在多個(gè)存儲(chǔ)介質(zhì)上。
需要把歷史數(shù)據(jù)和當(dāng)前的數(shù)據(jù)拆分開(kāi)。
例子:
當(dāng)伴隨著某一個(gè)表的數(shù)據(jù)量越來(lái)越大,以至于不能承受的時(shí)候,就需要對(duì)它進(jìn)行進(jìn)一步的切分。一種選擇是根據(jù)key 的范圍來(lái)做切分,譬如ID 為 1-10000的放到表A上,ID 為10000~20000的放到表B。這樣的擴(kuò)展就是可預(yù)見(jiàn)的。另一種是根據(jù)某一字段值來(lái)劃分,譬如根據(jù)用戶名的首字母,如果是A-D,就屬于表A,E-H就屬于表B。這樣做也存在不均衡性,當(dāng)某個(gè)范圍超出了單點(diǎn)所能承受的范圍就需要繼續(xù)切分。還有按日期切分等等。
可以使用Mrg_Myisam引擎實(shí)現(xiàn)水平分表。
優(yōu)點(diǎn):單表大小可控,天然水平擴(kuò)展。降低在查詢時(shí)需要讀的數(shù)據(jù)和索引的頁(yè)數(shù),同時(shí)也降低了索引的層數(shù),加快了查詢速度。
缺點(diǎn):無(wú)法解決集中寫(xiě)入瓶頸的問(wèn)題。同時(shí),水平分割會(huì)給應(yīng)用增加復(fù)雜度,它通常在查詢時(shí)需要多個(gè)表名,查詢所有數(shù)據(jù)需要union操作。在許多數(shù)據(jù)庫(kù)應(yīng)用中,這種復(fù)雜性會(huì)超過(guò)它帶來(lái)的優(yōu)點(diǎn),因?yàn)橹灰饕P(guān)鍵字不大,則在索引用于查詢時(shí),表中增加兩到三倍數(shù)據(jù)量,查詢時(shí)也就增加讀一個(gè)索引層的磁盤(pán)次數(shù)。
3)散列庫(kù)表(基于hash算法的切分):
定義:
表散列與水平分割相似,但沒(méi)有水平分割那樣的明顯分割界限,采用Hash算法把數(shù)據(jù)分散到各個(gè)分表中, 這樣IO更加均衡。一般采用mod來(lái)切分,一開(kāi)始確定切分?jǐn)?shù)據(jù)庫(kù)的個(gè)數(shù),通過(guò)hash取模來(lái)決定使用哪臺(tái)。這種方法能夠平均地來(lái)分配數(shù)據(jù),但是伴隨著數(shù)據(jù)量的增大,需要進(jìn)行擴(kuò)展的時(shí)候,這種方式無(wú)法做到在線擴(kuò)容。每增加節(jié)點(diǎn)的時(shí)候,就需要對(duì)hash 算法重新運(yùn)算。
我們會(huì)按照業(yè)務(wù)或者功能模塊將數(shù)據(jù)庫(kù)進(jìn)行分離,不同的模塊對(duì)應(yīng)不同的數(shù)據(jù)庫(kù)或者表,再按照一定的策略對(duì)某個(gè)頁(yè)面或者功能進(jìn)行更小的數(shù)據(jù)庫(kù)散列,比如用戶表,按照用戶ID進(jìn)行表散列,散列128張表,則應(yīng)就能夠低成本的提升系統(tǒng)的性能并且有很好的擴(kuò)展性
優(yōu)點(diǎn):
數(shù)據(jù)分布均勻
缺點(diǎn):
數(shù)據(jù)遷移的時(shí)候麻煩,不能按照機(jī)器性能分?jǐn)倲?shù)據(jù)
(二)在了解完分表了,我們先來(lái)理解區(qū)分分區(qū)與分表吧。
分區(qū):
定義:
分區(qū)和分表相似,都是按照規(guī)則分解表。不同在于分表將大表分解為若干個(gè)獨(dú)立的實(shí)體表,而分區(qū)是將數(shù)據(jù)分段劃分在多個(gè)位置存放,可以是同一塊磁盤(pán)也可以在不同的機(jī)器。分區(qū)后,表面上還是一張表,但數(shù)據(jù)散列到多個(gè)位置了。app讀寫(xiě)的時(shí)候操作的還是大表名字,db自動(dòng)去組織分區(qū)的數(shù)據(jù)。
分表定義:
分表是將一個(gè)大表按照一定的規(guī)則分解成多張具有獨(dú)立存儲(chǔ)空間的實(shí)體表,我們可以稱為子表,每個(gè)表都對(duì)應(yīng)三個(gè)文件,MYD數(shù)據(jù)文件,.MYI索引文件,.frm表結(jié)構(gòu)文件。這些子表可以分布在同一塊磁盤(pán)上,也可以在不同的機(jī)器上。app讀寫(xiě)的時(shí)候根據(jù)事先定義好的規(guī)則得到對(duì)應(yīng)的子表名,然后去操作它。
mysql分表和分區(qū)有什么聯(lián)系呢?:
1.都能提高mysql的性高,在高并發(fā)狀態(tài)下都有一個(gè)良好的表現(xiàn)。
2.分表和分區(qū)不矛盾,可以相互配合的,對(duì)于那些大訪問(wèn)量,并且表數(shù)據(jù)比較多的表,我們可以采取分表和分區(qū)結(jié)合的方式(如果merge這種分表方式,不能和分區(qū)配合的話,可以用其他的分表試),訪問(wèn)量不大,但是表數(shù)據(jù)很多的表,我們可以采取分區(qū)的方式等。
3.分表技術(shù)是比較麻煩的,需要手動(dòng)去創(chuàng)建子表,app服務(wù)端讀寫(xiě)時(shí)候需要計(jì)算子表名。采用merge好一些,但也要?jiǎng)?chuàng)建子表和配置子表間的union關(guān)系。
4.表分區(qū)相對(duì)于分表,操作方便,不需要?jiǎng)?chuàng)建子表。
(三)表拆分建議:(針對(duì)大系統(tǒng))
其實(shí)這點(diǎn)沒(méi)有明確的判斷標(biāo)準(zhǔn),比較依賴實(shí)際業(yè)務(wù)情況和經(jīng)驗(yàn)判斷。一般MySQL單表1000W左右的數(shù)據(jù)是沒(méi)有問(wèn)題的(前提是應(yīng)用系統(tǒng)和數(shù)據(jù)庫(kù)等層面設(shè)計(jì)和優(yōu)化的比較好)。
1)對(duì)記錄多的表進(jìn)行拆分。(幾百-上千萬(wàn)級(jí)別的表)
2)需要拆分的表分為動(dòng)態(tài)表和相對(duì)靜態(tài)表。動(dòng)態(tài)表拆分到不同庫(kù),靜態(tài)表存在于公共庫(kù)。從公共庫(kù)同步到分庫(kù)。實(shí)現(xiàn)表的連接。
3)按照年、月、地域等來(lái)分割,或者根據(jù)時(shí)間范圍、和很固定又清晰的字段值范圍等,具有確定的分割標(biāo)志來(lái)分割。
好了,MySQL優(yōu)化筆記(四)--表的設(shè)計(jì)與優(yōu)化(單表、多表)講完了,這是我學(xué)習(xí)優(yōu)化數(shù)據(jù)庫(kù)時(shí)候的筆記,這是積累的必經(jīng)一步,我會(huì)繼續(xù)出這個(gè)系列文章,分享經(jīng)驗(yàn)給大家。歡迎在下面指出錯(cuò)誤,共同學(xué)習(xí)!!你的點(diǎn)贊是對(duì)我最好的支持!!
總結(jié)
以上是生活随笔為你收集整理的物理机存放mysql实例原则_MySQL优化笔记(四)--表的设计与优化(单表、多表)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vb6.0动态加载odbc驱动(mysq
- 下一篇: yii2 session mysql_Y