MySQL優(yōu)化筆記(四)--表的設(shè)計(jì)與優(yōu)化(單表炕吸、多表)

前面講了SQL優(yōu)化以及索引的使用伐憾、設(shè)計(jì)優(yōu)化了,那么接下來就到表的設(shè)計(jì)與優(yōu)化啦:漳!J魉唷!真實(shí)地去設(shè)計(jì)優(yōu)化單表結(jié)構(gòu)以及講述多表設(shè)計(jì)基本原則(結(jié)合真實(shí)的生產(chǎn)環(huán)境的取舍來講述)瀑罗。

本系列demo下載

(一)MySQL優(yōu)化筆記(一)--庫與表基本操作以及數(shù)據(jù)增刪改

(二)MySQL優(yōu)化筆記(二)--查找優(yōu)化(1)(非索引設(shè)計(jì))

(三)MySQL優(yōu)化筆記(二)--查找優(yōu)化(2)(外連接胸嘴、多表聯(lián)合查詢以及查詢注意點(diǎn))

(四) MySQL優(yōu)化筆記(三)--索引的使用、原理和設(shè)計(jì)優(yōu)化

(五) MySQL優(yōu)化筆記(四)--表的設(shè)計(jì)與優(yōu)化(單表廓脆、多表)

(六)MySQL優(yōu)化筆記(五)--數(shù)據(jù)庫存儲引擎

(七)MySQL優(yōu)化筆記(六)--存儲過程和存儲函數(shù)

(八)MySQL優(yōu)化筆記(七)--視圖應(yīng)用詳解

(九) MySQL優(yōu)化筆記(八)--鎖機(jī)制超詳細(xì)解析(鎖分類筛谚、事務(wù)并發(fā)、引擎并發(fā)控制)


文章結(jié)構(gòu):(1)單表設(shè)計(jì)與優(yōu)化停忿;(2)基于單表設(shè)計(jì)的多表設(shè)計(jì)原則(含表拆分原則)驾讲;(均以實(shí)際生產(chǎn)開發(fā)環(huán)境下的環(huán)境為基準(zhǔn))

文章目錄:

(1)單表設(shè)計(jì)與優(yōu)化

  • 設(shè)計(jì)規(guī)范化表,消除數(shù)據(jù)冗余(以使用正確字段類型最明顯)
    - 前三范式
    - 所有字段類型
    - 所有字段類型羅列
    - 針對常用的varchar席赂,我們來思考幾個問題
    - 給出幾個類型選取建議
  • 適當(dāng)?shù)娜哂嗨泵黾佑?jì)算列:(實(shí)際開發(fā)中必須思考的點(diǎn))
  • 索引的設(shè)計(jì)
  • 主鍵和外鍵的必要性(實(shí)際項(xiàng)目開發(fā)的重要取舍)
  • 存儲過程、視圖颅停、函數(shù)的適當(dāng)使用(這些是優(yōu)化的方法谓晌,這幾個后面會講)
  • 傳說中的‘三少原則’
  • 分割你的表,減小表尺寸
  • 字段設(shè)計(jì)原則

(2)基于單表設(shè)計(jì)的多表設(shè)計(jì)原則

  • 表關(guān)系
    - 一對一關(guān)系
    - 一對多關(guān)系(多對一)
    - 多對多關(guān)系
    - 注意
    - 外鍵與索引
    - 建立關(guān)系
  • 分表原則:(涉及分區(qū)分表問題探究癞揉,以后的篇章再補(bǔ)充實(shí)例)
    - 表拆分方式
    - 垂直切分
    - 水平拆分(分表纸肉,分區(qū))–按表中某一字段值的范圍劃分
    - 散列庫表(基于hash算法的切分)
    - 在了解完分表了,我們先來理解區(qū)分分區(qū)與分表吧
    - 表拆分建議:(針對大系統(tǒng))

一喊熟、單表設(shè)計(jì)與優(yōu)化:

此部分基于此博客去拓展柏肪,寫下更貼近生產(chǎn)環(huán)境的數(shù)據(jù)表經(jīng)驗(yàn)

(1)設(shè)計(jì)規(guī)范化表,消除數(shù)據(jù)冗余(以使用正確字段類型最明顯):

數(shù)據(jù)庫范式是確保數(shù)據(jù)庫結(jié)構(gòu)合理芥牌,滿足各種查詢需要烦味、避免數(shù)據(jù)庫操作異常的數(shù)據(jù)庫設(shè)計(jì)方式。滿足范式要求的表壁拉,稱為規(guī)范化表谬俄,范式產(chǎn)生于20世紀(jì)70年代初柏靶,一般表設(shè)計(jì)滿足前三范式就可以,在這里簡單介紹一下前三范式溃论。

第一范式(1NF)無重復(fù)的列

所謂第一范式(1NF)是指在關(guān)系模型中屎蜓,對域添加的一個規(guī)范要求,所有的域都應(yīng)該是原子性的钥勋,即數(shù)據(jù)庫表的每一列都是不可分割的原子數(shù)據(jù)項(xiàng)梆靖,而不能是集合,數(shù)組笔诵,記錄等非原子數(shù)據(jù)項(xiàng)返吻。

第二范式(2NF)屬性

在1NF的基礎(chǔ)上,非碼屬性必須完全依賴于碼[在1NF基礎(chǔ)上消除非主屬性對主碼的部分函數(shù)依賴]

第三范式(3NF)屬性

在1NF基礎(chǔ)上乎婿,任何非主屬性不依賴于其它非主屬性[在2NF基礎(chǔ)上消除傳遞依賴测僵。

通俗點(diǎn)講:

第一范式:屬性(字段)的原子性約束,要求屬性具有原子性谢翎,不可再分割捍靠;

第二范式:記錄的惟一性約束,要求記錄有惟一標(biāo)識森逮,每條記錄需要有一個屬性來做為實(shí)體的唯一標(biāo)識榨婆,即每列都要和主鍵相關(guān)。

第三范式:屬性(字段)冗余性的約束褒侧,即任何字段不能由其他字段派生出來良风,在通俗點(diǎn)就是:主鍵沒有直接關(guān)系的數(shù)據(jù)列必須消除(消除的辦法就是再創(chuàng)建一個表來存放他們,當(dāng)然外鍵除外)闷供。即:確保每列都和主鍵列直接相關(guān),而不是間接相關(guān)烟央。

如果數(shù)據(jù)庫設(shè)計(jì)達(dá)到了完全的標(biāo)準(zhǔn)化,則把所有的表通過關(guān)鍵字連接在一起時歪脏,不會出現(xiàn)任何數(shù)據(jù)的復(fù)本(repetition)疑俭。標(biāo)準(zhǔn)化的優(yōu)點(diǎn)是明顯的,它避免了數(shù)據(jù)冗余婿失,自然就節(jié)省了空間钞艇,也對數(shù)據(jù)的一致性(consistency)提供了根本的保障,杜絕了數(shù)據(jù)不一致的現(xiàn)象豪硅,同時也提高了效率哩照。

尤其是正確字段類型的選擇:(先列出所有字段類型再寫建議)

所有字段類型:

(一)整型數(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ù)相對于定點(diǎn)數(shù)的優(yōu)點(diǎn)是在長度一定的情況下舟误,浮點(diǎn)數(shù)能夠表示更大的數(shù)據(jù)范圍葡秒;它的缺點(diǎn)是會引起精度問題姻乓。

使用時我們要注意:

1. 浮點(diǎn)數(shù)存在誤差問題嵌溢;
2. 對貨幣等對精度敏感的數(shù)據(jù)眯牧,應(yīng)該用定點(diǎn)數(shù)表示或存儲;
3. 編程中赖草,如果用到浮點(diǎn)數(shù)学少,要特別注意誤差問題,并盡量避免做浮點(diǎn)數(shù)比較秧骑;
4. 要注意浮點(diǎn)數(shù)中一些特殊值的處理版确。

(四)位類型

位類型 字節(jié)數(shù) 最小值 ~ 最大值
bit(m) 1~8 bit(1) ~ bit(64)

(五)日期時間類型

時間日期類型 字節(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年某個時刻
time 3 -838:59:59 ~ 838:59:59
year 1 1901 ~ 2155

mysql中用now()寫入當(dāng)前時間。

(六)字符串類型:

字符串類型 字節(jié)數(shù) 取值范圍
char(m) m m為0 ~ 255之間的整數(shù)
varchar(m) 值長度+1 m為0~65535之間的整數(shù)
tinytext 值長度+2 允許長度0~255字節(jié)
text 值長度+2 允許長度0~65535字節(jié)
mediumtext 值長度+3 允許長度0~167772150字節(jié)
longtext 值長度+3 允許長度0~4294967295字節(jié)
binary(m) m 允許0~m個字節(jié)定長的字符串
varbinary(m) 值長度+1 允許0~m個字節(jié)變長的字符串
tinyblob 值長度+1 允許長度0~255字節(jié)
blob 值長度+2 允許長度0~65535字節(jié)
mediumblob 值長度+3 允許長度0~167772150字節(jié)
longblob 值長度+4 允許長度0~4294967295字節(jié)
enum 1或2 1255個成員需要1個字節(jié)存乎折;25565535個成員绒疗,2個字節(jié)存
set 1/2/3/4/8 類似enum,set一次可以選取多個成員,而enum只能一個

針對常用的varchar骂澄,我們來思考幾個問題:

1)varchar的長度吓蘑?

MySQL的文檔,其中對varchar字段類型這樣描述:varchar(m) 變長字符串坟冲。m 表示最大列長度磨镶。m的范圍是0到65,535。(VARCHAR的最大實(shí)際長度由最長的行的大小和使用的字符集確定健提,最大有效長度是65,532字節(jié))琳猫。

mysql varchar(50) 不管中文 還是英文 都是存50個的,但是一個表中所有varchar字段的總長度跟編碼有關(guān)私痹,如果是utf-8脐嫂,那么大概65535/3,如果是gbk紊遵,那么大概65535/2.

2)存儲限制雹锣?編碼長度限制?行長度限制癞蚕?超出了蕊爵,會變成怎樣?

針對第一個問題:varchar 字段是將實(shí)際內(nèi)容單獨(dú)存儲在聚簇索引之外桦山,實(shí)際存儲從第二個字節(jié)開始攒射,接著要用1到2個字節(jié)表示實(shí)際長度(長度超過255時需要2個字節(jié)),因此最大長度不能超過65535恒水。

針對第二個問題:字符類型若為gbk会放,每個字符最多占2個字節(jié)。字符類型若為utf8钉凌,每個字符最多占3個字節(jié)咧最。

針對第三個問題:導(dǎo)致實(shí)際應(yīng)用中varchar長度限制的是一個行定義的長度。 MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值矢沿,則提示

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滥搭。

針對第四個問題:若定義的時候超過上述限制,則varchar字段會被強(qiáng)行轉(zhuǎn)為text類型捣鲸,并產(chǎn)生warning瑟匆。

3)與char的對比:

CHAR(M)定義的列的長度為固定的,M取值可以為0~255之間栽惶,當(dāng)保存CHAR值時愁溜,在它們的右邊填充空格以達(dá)到指定的長度。當(dāng)檢 索到CHAR值時外厂,尾部的空格被刪除掉冕象。在存儲或檢索過程中不進(jìn)行大小寫轉(zhuǎn)換。CHAR存儲定長數(shù)據(jù)很方便汁蝶,CHAR字段上的索引效率級高交惯,比如定義 char(10),那么不論你存儲的數(shù)據(jù)是否達(dá)到了10個字節(jié)穿仪,都要占去10個字節(jié)的空間,不足的自動用空格填充席爽。

CHAR和VARCHAR最大的不同就是一個是固定長度,一個是可變長度啊片。由于是可變長度只锻,因此實(shí)際存儲的時候是實(shí)際字符串再加上一個記錄 字符串長度的字節(jié)(如果超過255則需要兩個字節(jié))。如果分配給CHAR或VARCHAR列的值超過列的最大長度紫谷,則對值進(jìn)行裁剪以使其適合齐饮。如果被裁掉 的字符不是空格,則會產(chǎn)生一條警告笤昨。如果裁剪非空格字符祖驱,則會造成錯誤(而不是警告)并通過使用嚴(yán)格SQL模式禁用值的插入。

4)char瞒窒、varchar與text的建議:

TEXT只能儲存純文本文件捺僻。

效率來說基本是char>varchar>text,但是如果使用的是Innodb引擎的話崇裁,推薦使用varchar代替char

char和varchar可以有默認(rèn)值匕坯,text不能指定默認(rèn)值

以下給出幾個類型選取建議

(一)數(shù)字類型:

1)不到不要使用DOUBLE,不僅僅只是存儲長度的問題拔稳,同時還會存在精確性的問題葛峻。

2)固定精度的小數(shù),也不建議使用DECIMAL巴比,建議乘以固定倍數(shù)轉(zhuǎn)換成整數(shù)存儲术奖,可以大大節(jié)省存儲空間礁遵,且不會帶來任何附加維護(hù)成本。

3)對于整數(shù)的存儲采记,在數(shù)據(jù)量較大的情況下佣耐,建議區(qū)分開 TINYINT / INT / BIGINT 的選擇,因?yàn)槿咚加玫拇鎯臻g也有很大的差別挺庞,能確定不會使用負(fù)數(shù)的字段,建議添加unsigned定義稼病。當(dāng)然选侨,如果數(shù)據(jù)量較小的數(shù)據(jù)庫,也可以不用嚴(yán)格區(qū)分三個整數(shù)類型然走。

4)對于整型數(shù)值援制,mysql支持在類型名稱后面的小括號內(nèi)指定顯示寬度,例如int(5)表示當(dāng)數(shù)值寬度小于5位時候在數(shù)值前面填滿寬度芍瑞,一般配合zerofill屬性使用晨仑。如果一個列指定為zerofill,則MySQL自動為該列添加unsigned屬性。

5)在數(shù)據(jù)量較大時拆檬、建議把實(shí)數(shù)類型轉(zhuǎn)為整數(shù)類型洪己。原因很簡單:1. 浮點(diǎn)不精確;2.定點(diǎn)計(jì)算代價昂貴竟贯。例如:要存放財務(wù)數(shù)據(jù)精確到萬分之一答捕、則可以把所有金額乘以一百萬、然后存在BIGINT下屑那。

(二)字符類型:

1)盡量不要使用 TEXT 數(shù)據(jù)類型拱镐,其處理方式?jīng)Q定了他的性能要低于char或者是varchar類型的處理。定長字段持际,建議使用 CHAR 類型沃琅,不定長字段盡量使用 VARCHAR,且僅僅設(shè)定適當(dāng)?shù)淖畲箝L度蜘欲,而不是非常隨意的給一個很大的最大長度限定益眉,因?yàn)椴煌拈L度范圍,MySQL也會有不一樣的存儲處理姥份。

2)char會刪除字符串尾部的空格呜叫,varchar不會,varchar向前補(bǔ)1-2字節(jié)殿衰;char定長朱庆。binary類似于char,binary只能保存二進(jìn)制字符串。

char是固定長度闷祥,所以它的處理速度比varchar快得多娱颊,但缺點(diǎn)是浪費(fèi)存儲空間傲诵,不能在行尾保存空格。在MySQL中箱硕,MyISAM建議使用固定長度代替可變長度列拴竹;InnoDB建議使用varchar類型,因?yàn)樵贗nnoDB中剧罩,內(nèi)部行存儲格式?jīng)]有區(qū)分固定長度和可變長度惠昔。

3)enum類型忽略大小寫。

4)text與blob區(qū)別:blob保存二進(jìn)制數(shù)據(jù)镇防;text保存字符數(shù)據(jù)啦鸣,有字符集。text和blob不能有默認(rèn)值扑毡。

應(yīng)用:text與blob主要區(qū)別是text用來保存字符數(shù)據(jù)(如文章泉褐,日記等)疲眷,blob用來保存二進(jìn)制數(shù)據(jù)(如照片等)换淆。blob與text在執(zhí)行了大量刪除操作時候躁愿,有性能問題(產(chǎn)生大量的“空洞“)峡眶,為提高性能建議定期optimize table 對這類表進(jìn)行碎片整理。

關(guān)于text與blob我們有些看法建議:

1. BLOB和TEXT值也會引起自己的一些問題,特別是執(zhí)行了大量的刪除或更新操作的時候伞辛。刪除這種值會在數(shù)據(jù)表中留下很大的"空洞"于游,以后填入這些"空洞"的記錄可能長度不同,為了提高性能,建議定期使用 OPTIMIZE TABLE 功能對這類表進(jìn)行碎片整理.

2. 在不必要的時候避免檢索大型的BLOB或TEXT值蚜点。

3. 把BLOB或TEXT列分離到單獨(dú)的表中实辑。在某些環(huán)境中,如果把這些數(shù)據(jù)列移動到第二張數(shù)據(jù)表中藻丢,可以讓你把原數(shù)據(jù)表中 的數(shù)據(jù)列轉(zhuǎn)換為固定長度的數(shù)據(jù)行格式剪撬,那么它就是有意義的。這會減少主表中的碎片悠反,使你得到固定長度數(shù)據(jù)行的性能優(yōu)勢残黑。它還使你在主數(shù)據(jù)表上運(yùn)行 SELECT *查詢的時候不會通過網(wǎng)絡(luò)傳輸大量的BLOB或TEXT值馍佑。

(三)時間類型:

1)盡量使用TIMESTAMP類型,因?yàn)槠浯鎯臻g只需要 DATETIME 類型的一半梨水。對于只需要精確到某一天的數(shù)據(jù)類型拭荤,建議使用DATE類型,因?yàn)樗拇鎯臻g只需要3個字節(jié)疫诽,比TIMESTAMP還少舅世。不建議通過INT類型類存儲一個unix timestamp 的值,因?yàn)檫@太不直觀奇徒,會給維護(hù)帶來不必要的麻煩雏亚,同時還不會帶來任何好處。

2)根據(jù)實(shí)際需要選擇能夠滿足應(yīng)用的最小存儲日期類型摩钙。

3)timestamp罢低,日期類型中只有它能夠和實(shí)際時區(qū)相對應(yīng)。

(四)ENUM & SET:

對于狀態(tài)字段胖笛,可以嘗試使用 ENUM 來存放网持,因?yàn)榭梢詷O大的降低存儲空間,而且即使需要增加新的類型匀钧,只要增加于末尾翎碑,修改結(jié)構(gòu)也不需要重建表數(shù)據(jù)谬返。如果是存放可預(yù)先定義的屬性數(shù)據(jù)呢之斯?可以嘗試使用SET類型,即使存在多種屬性遣铝,同樣可以游刃有余佑刷,同時還可以節(jié)省不小的存儲空間。

(五)LOB類型:

強(qiáng)烈反對在數(shù)據(jù)庫中存放 LOB 類型數(shù)據(jù)酿炸,雖然數(shù)據(jù)庫提供了這樣的功能瘫絮,但這不是他所擅長的,我們更應(yīng)該讓合適的工具做他擅長的事情填硕,才能將其發(fā)揮到極致麦萤。

(2)適當(dāng)?shù)娜哂啵黾佑?jì)算列:(實(shí)際開發(fā)中必須思考的點(diǎn))

數(shù)據(jù)庫設(shè)計(jì)的實(shí)用原則是:在數(shù)據(jù)冗余和處理速度之間找到合適的平衡點(diǎn)扁眯。

滿足范式的表一定是規(guī)范化的表壮莹,但不一定是最佳的設(shè)計(jì)。很多情況下會為了提高數(shù)據(jù)庫的運(yùn)行效率姻檀,常常需要降低范式標(biāo)準(zhǔn):適當(dāng)增加冗余命满,達(dá)到以空間換時間的目的。比如我們有一個表绣版,產(chǎn)品名稱胶台,單價歼疮,庫存量,總價值诈唬。這個表是不滿足第三范式的韩脏,因?yàn)椤翱們r值”可以由“單價”乘以“數(shù)量”得到,說明“金額”是冗余字段铸磅。但是骤素,增加“總價值”這個冗余字段,可以提高查詢統(tǒng)計(jì)的速度愚屁,這就是以空間換時間的作法济竹。合理的冗余可以分散數(shù)據(jù)量大的表的并發(fā)壓力,也可以加快特殊查詢的速度霎槐,冗余字段可以有效減少數(shù)據(jù)庫表的連接送浊,提高效率。

其中"總價值"就是一個計(jì)算列丘跌,在數(shù)據(jù)庫中有兩種類型:數(shù)據(jù)列和計(jì)算列袭景,數(shù)據(jù)列就是需要我們手動或者程序給予賦值的列,計(jì)算列是源于表中其他的數(shù)據(jù)計(jì)算得來闭树,比如這里的"總價值"

在SQL中創(chuàng)建計(jì)算列:

create table goods(
   id int auto_increment not null,
   c1 int, 
   c2 int, 
   c3 int as (c1+c2), //這個就是計(jì)算列啦
   primary key(id)
 ) 

(3)索引的設(shè)計(jì):

表優(yōu)化的重要途徑耸棒,百萬級別的表沒有索引,注定卡死报辱。

詳細(xì)請閱讀此文章

(4)主鍵和外鍵的必要性(實(shí)際項(xiàng)目開發(fā)的重要取舍)

概述:主鍵與外鍵的設(shè)計(jì)与殃,在全局?jǐn)?shù)據(jù)庫的設(shè)計(jì)中,占有重要地位碍现。 因?yàn)椋褐麈I是實(shí)體的抽象幅疼,主鍵與外鍵的配對,表示實(shí)體之間的連接昼接。

主鍵:根據(jù)第二范式爽篷,需要有一個字段去標(biāo)識這條記錄,主鍵無疑是最好的標(biāo)識慢睡,但是很多表也不一定需要主鍵逐工,但是對于數(shù)據(jù)量大,查詢頻繁的數(shù)據(jù)庫表漂辐,一定要有主鍵泪喊,主鍵可以增加效率、防止重復(fù)等優(yōu)點(diǎn)者吁。

主鍵的選擇也比較重要窘俺,一般選擇總的長度小的鍵,小的鍵的比較速度快,同時小的鍵可以使主鍵的B樹結(jié)構(gòu)的層次更少瘤泪。

主鍵的選擇還要注意組合主鍵的字段次序灶泵,對于組合主鍵來說,不同的字段次序的主鍵的性能差別可能會很大对途,一般應(yīng)該選擇重復(fù)率低赦邻、單獨(dú)或者組合查詢可能性大的字段放在前面。

外鍵:外鍵作為數(shù)據(jù)庫對象实檀,很多人認(rèn)為麻煩而不用惶洲,實(shí)際上犁嗅,外鍵在大部分情況下是很有用的赘娄,理由是:外鍵是最高效的一致性維護(hù)方法。

數(shù)據(jù)庫的一致性要求遥诉,依次可以用外鍵须床、CHECK約束铐料、規(guī)則約束、觸發(fā)器豺旬、客戶端程序钠惩,一般認(rèn)為,離數(shù)據(jù)越近的方法效率越高族阅。但是B恕!坦刀!要謹(jǐn)慎使用級聯(lián)刪除和級聯(lián)更新愧沟,因?yàn)榧壜?lián)刪除和級聯(lián)更新有些突破了傳統(tǒng)的關(guān)于外鍵的定義,功能有點(diǎn)太過強(qiáng)大求泰,使用前必須確定自己已經(jīng)把握好其功能范圍央渣,否則计盒,級聯(lián)刪除和級聯(lián)更新可能讓你的數(shù)據(jù)莫名其妙的被修改或者丟失渴频。從性能看級聯(lián)刪除和級聯(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. 針對性能要求不高,安全要求高的模塊懈涛,推薦使用物理主外鍵關(guān)聯(lián)逛万;針對性能要求高、安全自己控制的模塊批钠,推薦不用物理外鍵宇植;

2. 針對中心模塊和其他模塊的聯(lián)系得封,推薦使用物理主外鍵。

3. 針對熱點(diǎn)模塊指郁,必須使用邏輯主外鍵

4. 針對邊緣模塊忙上,推薦使用物理主外鍵

小系統(tǒng)?闲坎?

隨便你啦疫粥,也就是20張表以下的系統(tǒng)。邏輯不復(fù)雜都無所謂啦腰懂,不過推薦還是使用外鍵梗逮。

注意:

不用外鍵而用程序控制數(shù)據(jù)一致性和完整性時,應(yīng)該寫一層來保證绣溜,然后個個應(yīng)用通過這個層來訪問數(shù)據(jù)庫库糠。

外鍵是有性能問題的,不能過分追求涮毫。

(5)存儲過程瞬欧、視圖、函數(shù)的適當(dāng)使用(這些是優(yōu)化的方法罢防,這幾個后面會講):

很多人習(xí)慣將復(fù)雜操作都放在應(yīng)用程序?qū)铀一ⅲ绻阋獌?yōu)化數(shù)據(jù)訪問性能,將SQL代碼移植到數(shù)據(jù)庫上(使用存儲過程咒吐,視圖野建,函數(shù)和觸發(fā)器)也是一個很大的改進(jìn)原因如下:

1)存儲過程減少了網(wǎng)絡(luò)傳輸、處理及存儲的工作量恬叹,且經(jīng)過編譯和優(yōu)化候生,執(zhí)行速度快,易于維護(hù)绽昼,且表的結(jié)構(gòu)改變時唯鸭,不影響客戶端的應(yīng)用程序

2)使用存儲過程,視圖硅确,函數(shù)有助于減少應(yīng)用程序中SQL復(fù)制的弊端目溉,因?yàn)楝F(xiàn)在只在一個地方集中處理SQL

3)使用數(shù)據(jù)庫對象實(shí)現(xiàn)所有的TSQL有助于分析TSQL的性能問題,同時有助于你集中管理TSQL代碼菱农,更好的重構(gòu)TSQL代碼缭付。

(6)傳說中的‘三少原則’:

1)數(shù)據(jù)庫的表越少越好

2)表的字段越少越好

3)字段中的組合主鍵、組合索引越少越好

這里的少是相對的循未,是減少數(shù)據(jù)冗余的重要設(shè)計(jì)理念而已陷猫。

實(shí)際上,我們?yōu)榱藴p少單表查詢壓力,會把去分表绣檬,從而分發(fā)記錄量舅巷,避免一個超級表的誕生。

(7)分割你的表河咽,減小表尺寸

如果你發(fā)現(xiàn)某個表的記錄太多钠右,例如超過一千萬條,則要對該表進(jìn)行水平分割忘蟹。水平分割的做法是飒房,以該表主鍵的某個值為界線,將該表的記錄水平分割為兩個表媚值。

如果你若發(fā)現(xiàn)某個表的字段太多狠毯,例如超過八十個,則垂直分割該表褥芒,將原來的一個表分解為兩個表

(8)字段設(shè)計(jì)原則:

字段是數(shù)據(jù)庫最基本的單位嚼松,其設(shè)計(jì)對性能的影響是很大的。需要注意如下:

1)數(shù)據(jù)類型盡量用數(shù)字型锰扶,數(shù)字型的比較比字符型的快很多献酗。

2)數(shù)據(jù)類型盡量小,這里的盡量小是指在滿足可以預(yù)見的未來需求的前提下的坷牛。

3)盡量不要允許NULL罕偎,除非必要,可以用NOT NULL+DEFAULT代替京闰。

NULL 類型比較特殊颜及,SQL 難優(yōu)化。雖然 MySQL NULL類型和 Oracle 的NULL 有差異蹂楣,會進(jìn)入索引中俏站,但如果是一個組合索引,那么這個NULL 類型的字段會極大影響整個索引的效率痊土。此外肄扎,NULL 在索引中的處理也是特殊的,也會占用額外的存放空間施戴。

4)少用TEXT和IMAGE反浓,二進(jìn)制字段的讀寫是比較慢的,而且赞哗,讀取的方法也不多,大部分情況下最好不用辆雾。

5)自增字段要慎用肪笋,不利于數(shù)據(jù)遷移


二、基于單表設(shè)計(jì)的多表設(shè)計(jì)原則:

(1)表關(guān)系:

一)一對一關(guān)系:

定義:

在這種關(guān)系中,關(guān)系表的每一邊都只能存在一個記錄藤乙。每個數(shù)據(jù)表中的關(guān)鍵字在對應(yīng)的關(guān)系表中只能存在一個記錄或者沒有對應(yīng)的記錄猜揪。這種關(guān)系和一對配偶之間的關(guān)系非常相似——要么你已經(jīng)結(jié)婚,你和你的配偶只能有一個配偶坛梁,要么你沒有結(jié)婚沒有配偶而姐。大多數(shù)的一對一的關(guān)系都是某種商業(yè)規(guī)則約束的結(jié)果,而不是按照數(shù)據(jù)的自然屬性來得到的划咐。如果沒有這些規(guī)則的約束拴念,你通常可以把兩個數(shù)據(jù)表合并進(jìn)一個數(shù)據(jù)表褐缠,而且不會打破任何規(guī)范化的規(guī)則政鼠。

一對一關(guān)系又分為:一對一外鍵關(guān)聯(lián)和一對一主鍵關(guān)聯(lián)。

一對一主鍵關(guān)聯(lián):要求兩個表的主鍵必須完全一致队魏,通過兩個表的主鍵建立關(guān)聯(lián)關(guān)系公般。

可以看到下圖,很明顯的胡桨,班級編號作為主鍵的話官帘,就是一個主鍵關(guān)聯(lián)了。

這里寫圖片描述

一對一外鍵關(guān)聯(lián):

下面又很明顯看到昧谊,以班主任ID作為外鍵關(guān)聯(lián)起來的一個表遏佣。

這里寫圖片描述

二)一對多關(guān)系(多對一):

定義:

主鍵數(shù)據(jù)表中只能含有一個記錄,而在其關(guān)系表中這條記錄可以與一個或者多個記錄相關(guān)揽浙,也可以沒有記錄與之相關(guān)状婶。這種關(guān)系類似于你和你的父母之間的關(guān)系。你只有一位母親馅巷,但是你母親可以有幾個孩子膛虫。

下圖可以看到:一對多-班級表有多個學(xué)生;多對一-多個學(xué)生屬于一個班級钓猬。

這里寫圖片描述

三)多對多關(guān)系:

定義:

兩個數(shù)據(jù)表里的每條記錄都可以和另一個數(shù)據(jù)表里任意數(shù)量的記錄(或者沒有記錄)相關(guān)稍刀。例如,如果你有多個兄弟姐妹敞曹,這對你的兄弟姐妹也是一樣(有多個兄弟姐妹)账月,多對多這種關(guān)系需要引入第三個數(shù)據(jù)表,這種數(shù)據(jù)表稱為聯(lián)系表或者連接表澳迫,因?yàn)殛P(guān)系型系統(tǒng)不能直接實(shí)現(xiàn)這種關(guān)系局齿。

在RDBMS中,必須使用中間表來表示多對多的關(guān)系橄登。中間表我們可以分成兩種抓歼,一種是純粹表示關(guān)系的中間表讥此,一種是表示中間實(shí)體的中間表。

純粹表示關(guān)系的中間表很簡單谣妻,只需要兩列:AID和BID萄喳,AID以外鍵關(guān)聯(lián)到A表的主鍵,BID以外鍵關(guān)聯(lián)到B表的主鍵蹋半,然后這兩個列組成聯(lián)合主鍵他巨。這個中間表純粹是表示多對多關(guān)系而存在,在業(yè)務(wù)上不會有對應(yīng)的實(shí)體與之對應(yīng)减江。比如前面提到的學(xué)生和課程的關(guān)系染突,如果我們只需要知道哪些學(xué)生上哪些課,哪些課有哪些學(xué)生選您市,不需要有更多的信息的情況下觉痛,我們就可以建立“學(xué)生課程”中間表,里面只有學(xué)生ID和課程ID兩個字段茵休。

這里寫圖片描述

中間實(shí)體是在純粹的中間關(guān)系表的基礎(chǔ)上薪棒,加上了更多的屬性,從而形成了一個新的實(shí)體榕莺。比如上面提到的學(xué)生和課程的關(guān)系俐芯,如果我們需要記錄學(xué)生選課的時間、學(xué)生選擇這門課程后的考試成績钉鸯,那么我們就像建立一個“選課”實(shí)體吧史,該實(shí)體具有如下屬性:

選課ID,主鍵
學(xué)生ID唠雕,與學(xué)生表做外鍵關(guān)聯(lián)
課程ID贸营,與課程表做外鍵關(guān)聯(lián)
選課時間,DateTime類型
考試成績岩睁,記錄選修該課程后考試的最終成績

注意:

一)外鍵與索引:

外鍵是一種約束钞脂,與索引的概念不一樣,只是大多數(shù)情況下捕儒,我們建立外鍵時冰啃,都會在外鍵列上建立對應(yīng)的索引。外鍵的存在會在每一次數(shù)據(jù)插入刘莹、修改時進(jìn)行約束檢查阎毅,如果不滿足外鍵約束,則禁止數(shù)據(jù)的插入或修改点弯,這必然帶來一個問題扇调,就是在數(shù)據(jù)量特別大的情況下,每一次約束檢查必然導(dǎo)致性能的下降蒲拉。索引其實(shí)也有類似的問題肃拜,索引如果建多了痴腌,那么在插入刪除修改數(shù)據(jù)時也要去維護(hù)對應(yīng)的索引雌团,所以索引的存在也會導(dǎo)致數(shù)據(jù)操作變慢燃领。

不過外鍵與索引的優(yōu)點(diǎn)不同,外鍵只是保證數(shù)據(jù)的一致性锦援,并不能給系統(tǒng)性能帶來任何好處猛蔽,所以由于外鍵導(dǎo)致的插入數(shù)據(jù)變慢會隨著數(shù)據(jù)量的增長而越來越嚴(yán)重。而索引的目的是為了檢索數(shù)據(jù)更快灵寺,維護(hù)數(shù)據(jù)時導(dǎo)致的索引數(shù)據(jù)的變更曼库,對性能的影響不會像外鍵那樣隨著數(shù)據(jù)量增長而變得嚴(yán)重(當(dāng)然大數(shù)量時的索引樹維護(hù)會比小數(shù)據(jù)量的索引樹維護(hù)更麻煩,但至少不是像外鍵那樣)略板。

出于性能的考慮毁枯,如果我們的系統(tǒng)完全由我們開發(fā)的程序使用,而不需要提供數(shù)據(jù)庫給其他應(yīng)用系統(tǒng)寫入數(shù)據(jù)叮称,而且對性能要求較高种玛,那么我們可以考慮在生產(chǎn)環(huán)境中不使用外鍵,只需要建立能夠提高性能的索引瓤檐。由于整個數(shù)據(jù)庫的操作都是由我們開發(fā)的程序來完成的赂韵,所以我們程序可以在開發(fā)過程中做好各方面的一致性檢查,保證操作的數(shù)據(jù)是滿足外鍵約束的挠蛉,而不需要真正的存在這樣一個外鍵約束祭示。怎么做到這一點(diǎn)呢,首先谴古,我們在建立數(shù)據(jù)庫時有多個腳本质涛,包括創(chuàng)建表、創(chuàng)建初始化數(shù)據(jù)掰担、創(chuàng)建索引汇陆、創(chuàng)建外鍵等,我們在開發(fā)和測試環(huán)境中恩敌,都把這些腳本運(yùn)行了瞬测,以使開發(fā)測試環(huán)境中的數(shù)據(jù)庫是完整的,經(jīng)過大量測試保證應(yīng)用程序能夠維護(hù)數(shù)據(jù)之間的約束的情況下纠炮,那么我們在生產(chǎn)時月趟,并不需要運(yùn)行創(chuàng)建外鍵這個腳本文件,只需要創(chuàng)建表恢口、初始化數(shù)據(jù)孝宗、創(chuàng)建索引等即可。

二)建立關(guān)系

在開始著手考慮建立關(guān)系表之間的關(guān)系之前耕肩,你可能需要對數(shù)據(jù)非常熟悉因妇。只有在熟悉數(shù)據(jù)之后问潭,關(guān)聯(lián)會比你剛開始的時候更明顯。你的數(shù)據(jù)庫系統(tǒng)依賴于在兩個數(shù)據(jù)表中找到的匹配值來建立關(guān)系婚被。

進(jìn)行匹配的值都是主鍵和外鍵的值狡忙。(關(guān)系模型不要求一個關(guān)系必須對應(yīng)的使用一個主鍵來確定。你可以使用數(shù)據(jù)表中的任何備選關(guān)鍵字來建立關(guān)系址芯,但是使用主鍵是大家都已經(jīng)接受的標(biāo)準(zhǔn)灾茁。)主鍵(primary key)唯一的識別表中的每個記錄。而外鍵(foreign key)只是簡單的將一個數(shù)據(jù)表中的主鍵存放在另外一個數(shù)據(jù)表中谷炸。同樣地北专,對于你來說也不需要做太多的工作——只是簡單地將主鍵加到關(guān)系表中,并將其定義為外鍵旬陡。

<font color=#FF7F50 size=5>(2)分表原則:</font>(涉及分區(qū)分表問題探究拓颓,以后的篇章再補(bǔ)充實(shí)例)

分表主要目的是為突破單節(jié)點(diǎn)數(shù)據(jù)庫服務(wù)器的 I/O 能力限制,解決數(shù)據(jù)庫擴(kuò)展性問題描孟。 同時分表分庫等思想也將引出以后的數(shù)據(jù)庫集群驶睦,主從復(fù)制、讀寫分離方案.....

為什么我們要分表分區(qū)画拾?啥繁??

日常開發(fā)中我們經(jīng)常會遇到大表的情況青抛,所謂的大表是指存儲了百萬級乃至千萬級條記錄的表旗闽。這樣的表過于龐大,導(dǎo)致數(shù)據(jù)庫在查詢和插入的時候耗時太長蜜另,性能低下适室,如果涉及聯(lián)合查詢的情況,性能會更加糟糕举瑰。分表和表分區(qū)的目的就是減少數(shù)據(jù)庫的負(fù)擔(dān)捣辆,提高數(shù)據(jù)庫的效率,通常點(diǎn)來講就是提高表的增刪改查效率此迅。

(一)表拆分方式:

1)垂直切分:

這里寫圖片描述

定義:

把主鍵和一些數(shù)據(jù)表的列放在一個表中汽畴,然后把主鍵和另一些數(shù)據(jù)表的列放在一個表中。

如果一個表的某些列常用耸序,另一些不常用忍些,則可以采用垂直拆分。垂直拆分可以使數(shù)據(jù)行變小坎怪,一個數(shù)據(jù)頁就可以存放更多的數(shù)據(jù)罢坝,在查詢時候可以減少I/O次數(shù)。其缺點(diǎn)是需要管理冗余列搅窿,查詢所有數(shù)據(jù)時候需要join查找嘁酿。

優(yōu)點(diǎn):

使得行數(shù)據(jù)變小隙券,一個數(shù)據(jù)塊(Block)就能存放更多的數(shù)據(jù),在查詢時就會減少I/O次數(shù)(每次查詢時讀取的Block 就少)闹司。
可以達(dá)到最大化利用Cache的目的娱仔。

缺點(diǎn):

表垂直分割后,主碼(主鍵)出現(xiàn)冗余开仰,需要管理冗余列
會引起表連接JOIN操作(增加CPU開銷)需要從業(yè)務(wù)上規(guī)避

2)水平拆分(分表拟枚,分區(qū))--按表中某一字段值的范圍劃分:

這里寫圖片描述

定義:

根據(jù)列的范圍值進(jìn)行合理切分薪铜,放在多個獨(dú)立的表或分區(qū)中众弓。

適用場景:

表很大,分割后可以降低查詢時候需要讀取的數(shù)據(jù)和索引的頁數(shù)隔箍,同時降低索引的層數(shù)谓娃,提高查詢速度。
表中的數(shù)據(jù)是獨(dú)立的蜒滩,例如表中分別記錄各個地區(qū)的數(shù)據(jù)或不同時期的數(shù)據(jù)滨达,特別是有些數(shù)據(jù)常用,而另一些數(shù)據(jù)不常用俯艰。
需要把數(shù)據(jù)放在多個存儲介質(zhì)上捡遍。
需要把歷史數(shù)據(jù)和當(dāng)前的數(shù)據(jù)拆分開。

例子:

當(dāng)伴隨著某一個表的數(shù)據(jù)量越來越大竹握,以至于不能承受的時候画株,就需要對它進(jìn)行進(jìn)一步的切分。一種選擇是根據(jù)key 的范圍來做切分啦辐,譬如ID 為 1-10000的放到表A上谓传,ID 為10000~20000的放到表B。這樣的擴(kuò)展就是可預(yù)見的芹关。另一種是根據(jù)某一字段值來劃分续挟,譬如根據(jù)用戶名的首字母,如果是A-D侥衬,就屬于表A诗祸,E-H就屬于表B。這樣做也存在不均衡性轴总,當(dāng)某個范圍超出了單點(diǎn)所能承受的范圍就需要繼續(xù)切分直颅。還有按日期切分等等。

可以使用Mrg_Myisam引擎實(shí)現(xiàn)水平分表肘习。

優(yōu)點(diǎn):單表大小可控际乘,天然水平擴(kuò)展。降低在查詢時需要讀的數(shù)據(jù)和索引的頁數(shù)漂佩,同時也降低了索引的層數(shù)脖含,加快了查詢速度罪塔。

缺點(diǎn):無法解決集中寫入瓶頸的問題。同時养葵,水平分割會給應(yīng)用增加復(fù)雜度征堪,它通常在查詢時需要多個表名,查詢所有數(shù)據(jù)需要union操作关拒。在許多數(shù)據(jù)庫應(yīng)用中佃蚜,這種復(fù)雜性會超過它帶來的優(yōu)點(diǎn),因?yàn)橹灰饕P(guān)鍵字不大着绊,則在索引用于查詢時谐算,表中增加兩到三倍數(shù)據(jù)量,查詢時也就增加讀一個索引層的磁盤次數(shù)归露。

3)散列庫表(基于hash算法的切分):

定義:

表散列與水平分割相似洲脂,但沒有水平分割那樣的明顯分割界限,采用Hash算法把數(shù)據(jù)分散到各個分表中, 這樣IO更加均衡剧包。一般采用mod來切分恐锦,一開始確定切分?jǐn)?shù)據(jù)庫的個數(shù),通過hash取模來決定使用哪臺疆液。這種方法能夠平均地來分配數(shù)據(jù)一铅,但是伴隨著數(shù)據(jù)量的增大,需要進(jìn)行擴(kuò)展的時候堕油,這種方式無法做到在線擴(kuò)容潘飘。每增加節(jié)點(diǎn)的時候,就需要對hash 算法重新運(yùn)算馍迄。

我們會按照業(yè)務(wù)或者功能模塊將數(shù)據(jù)庫進(jìn)行分離福也,不同的模塊對應(yīng)不同的數(shù)據(jù)庫或者表,再按照一定的策略對某個頁面或者功能進(jìn)行更小的數(shù)據(jù)庫散列攀圈,比如用戶表暴凑,按照用戶ID進(jìn)行表散列,散列128張表赘来,則應(yīng)就能夠低成本的提升系統(tǒng)的性能并且有很好的擴(kuò)展性

優(yōu)點(diǎn):

數(shù)據(jù)分布均勻

缺點(diǎn):

數(shù)據(jù)遷移的時候麻煩现喳,不能按照機(jī)器性能分?jǐn)倲?shù)據(jù)

(二)在了解完分表了,我們先來理解區(qū)分分區(qū)與分表吧犬辰。

分區(qū):

定義:

分區(qū)和分表相似嗦篱,都是按照規(guī)則分解表。不同在于分表將大表分解為若干個獨(dú)立的實(shí)體表幌缝,而分區(qū)是將數(shù)據(jù)分段劃分在多個位置存放灸促,可以是同一塊磁盤也可以在不同的機(jī)器。分區(qū)后,表面上還是一張表浴栽,但數(shù)據(jù)散列到多個位置了荒叼。app讀寫的時候操作的還是大表名字,db自動去組織分區(qū)的數(shù)據(jù)典鸡。

分表定義:

分表是將一個大表按照一定的規(guī)則分解成多張具有獨(dú)立存儲空間的實(shí)體表被廓,我們可以稱為子表,每個表都對應(yīng)三個文件萝玷,MYD數(shù)據(jù)文件嫁乘,.MYI索引文件,.frm表結(jié)構(gòu)文件球碉。這些子表可以分布在同一塊磁盤上蜓斧,也可以在不同的機(jī)器上。app讀寫的時候根據(jù)事先定義好的規(guī)則得到對應(yīng)的子表名汁尺,然后去操作它法精。

mysql分表和分區(qū)有什么聯(lián)系呢?:

1.都能提高mysql的性高痴突,在高并發(fā)狀態(tài)下都有一個良好的表現(xiàn)。

2.分表和分區(qū)不矛盾狼荞,可以相互配合的辽装,對于那些大訪問量,并且表數(shù)據(jù)比較多的表相味,我們可以采取分表和分區(qū)結(jié)合的方式(如果merge這種分表方式拾积,不能和分區(qū)配合的話,可以用其他的分表試)丰涉,訪問量不大拓巧,但是表數(shù)據(jù)很多的表,我們可以采取分區(qū)的方式等一死。

3.分表技術(shù)是比較麻煩的肛度,需要手動去創(chuàng)建子表,app服務(wù)端讀寫時候需要計(jì)算子表名投慈。采用merge好一些承耿,但也要創(chuàng)建子表和配置子表間的union關(guān)系。

4.表分區(qū)相對于分表伪煤,操作方便加袋,不需要創(chuàng)建子表。

(三)表拆分建議:(針對大系統(tǒng))

其實(shí)這點(diǎn)沒有明確的判斷標(biāo)準(zhǔn)抱既,比較依賴實(shí)際業(yè)務(wù)情況和經(jīng)驗(yàn)判斷职烧。一般MySQL單表1000W左右的數(shù)據(jù)是沒有問題的(前提是應(yīng)用系統(tǒng)和數(shù)據(jù)庫等層面設(shè)計(jì)和優(yōu)化的比較好)。

1)對記錄多的表進(jìn)行拆分。(幾百-上千萬級別的表)

2)需要拆分的表分為動態(tài)表和相對靜態(tài)表蚀之。動態(tài)表拆分到不同庫跋理,靜態(tài)表存在于公共庫。從公共庫同步到分庫恬总。實(shí)現(xiàn)表的連接前普。

3)按照年、月壹堰、地域等來分割拭卿,或者根據(jù)時間范圍、和很固定又清晰的字段值范圍等贱纠,具有確定的分割標(biāo)志來分割峻厚。


好了,MySQL優(yōu)化筆記(四)--表的設(shè)計(jì)與優(yōu)化(單表谆焊、多表)講完了惠桃,這是我學(xué)習(xí)優(yōu)化數(shù)據(jù)庫時候的筆記,這是積累的必經(jīng)一步辖试,我會繼續(xù)出這個系列文章辜王,分享經(jīng)驗(yàn)給大家。歡迎在下面指出錯誤罐孝,共同學(xué)習(xí)D殴荨!你的點(diǎn)贊是對我最好的支持Aぁ汹来!

更多內(nèi)容,可以訪問JackFrost的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末改艇,一起剝皮案震驚了整個濱河市收班,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谒兄,老刑警劉巖摔桦,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舵变,居然都是意外死亡酣溃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門纪隙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赊豌,“玉大人,你說我怎么就攤上這事绵咱〉獗” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艾恼。 經(jīng)常有香客問我住涉,道長,這世上最難降的妖魔是什么钠绍? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任舆声,我火速辦了婚禮,結(jié)果婚禮上柳爽,老公的妹妹穿的比我還像新娘媳握。我一直安慰自己,他們只是感情好磷脯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布蛾找。 她就那樣靜靜地躺著,像睡著了一般赵誓。 火紅的嫁衣襯著肌膚如雪打毛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天俩功,我揣著相機(jī)與錄音幻枉,去河邊找鬼。 笑死绑雄,一個胖子當(dāng)著我的面吹牛展辞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播万牺,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼洽腺!你這毒婦竟也來了脚粟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蘸朋,失蹤者是張志新(化名)和其女友劉穎核无,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藕坯,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡团南,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了炼彪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吐根。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辐马,靈堂內(nèi)的尸體忽然破棺而出拷橘,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布冗疮,位于F島的核電站萄唇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏术幔。R本人自食惡果不足惜另萤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诅挑。 院中可真熱鬧四敞,春花似錦、人聲如沸揍障。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毒嫡。三九已至癌蚁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兜畸,已是汗流浹背努释。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咬摇,地道東北人伐蒂。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像肛鹏,于是被迫代替她去往敵國和親逸邦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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