索引
數(shù)據(jù)庫中的查詢操作非常普遍,索引就是提升查找速度的一種手段
索引的類型
從數(shù)據(jù)結(jié)構(gòu)角度分
1.B+索引:
傳統(tǒng)意義上的索引,最常用最普遍的索引
2.hash索引:
hash索引是一種自適應(yīng)的索引,數(shù)據(jù)庫會根據(jù)表的使用情況自動生成hash索引,人為無法干預(yù)
3.全文索引:
用于實現(xiàn)關(guān)鍵詞搜索,但它只能根據(jù)空格分詞,因此不支持中文,可以使用lucene實現(xiàn)搜索功能
4.RTree索引:
在mysql很少使用,僅支持geometry數(shù)據(jù)類型;相對于BTREE,RTREE的優(yōu)勢在于范圍
物理存儲角度
數(shù)據(jù)庫以頁為存儲單位,一個頁有8K(8192byte),一頁存放N條記錄
在B+樹中分為數(shù)據(jù)頁和索引頁
B+樹的高一般為2-4層,因為查找某一鍵值的記錄只需要2-4次I/O,效率較高
1.聚集索引(也叫聚簇索引)
2.非聚集索引
好文:
[https://www.cnblogs.com/s-b-b/p/8334593.html]
不管是聚集索引還是非聚集索引他們的結(jié)構(gòu)都是B+樹,他們的唯一區(qū)別是
聚集索引的數(shù)據(jù)頁存放的是完整的記錄,也就是說,聚集索引決定了表的物理存儲順序
非聚集索引的數(shù)據(jù)頁中存放的是指向記錄的地址信息,他真正的數(shù)據(jù)已經(jīng)在聚集索引中存儲了
1、聚集索引一個表只能有一個,而非聚集索引一個表可以存在多個
2、聚集索引存儲記錄是物理上連續(xù)存在,而非聚集索引是邏輯上的連續(xù),物理存儲并不連續(xù)
在聚集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同,一個表只能包含一個聚集索引,聚集索引比非聚集索引有更快的訪問速度
索引是在存儲引擎層實現(xiàn)的,而不是在服務(wù)器層實現(xiàn)的,所以不同存儲引擎具有不同的索引類型和實現(xiàn)。
術(shù)語“聚簇”表示數(shù)據(jù)行和相鄰的鍵值緊密地存儲在一起,InnoDB 的聚簇索引的數(shù)據(jù)行存放在 B+Tree 的葉子頁中。
因為無法把數(shù)據(jù)行存放在兩個不同的地方,所以一個表只能有一個聚簇索引。
優(yōu)點
- 可以把相關(guān)數(shù)據(jù)保存在一起,減少 I/O 操作;
- 因為數(shù)據(jù)保存在 B+Tree 中,因此數(shù)據(jù)訪問更快。
缺點 - 聚簇索引最大限度提高了 I/O 密集型應(yīng)用的性能,但是如果數(shù)據(jù)全部放在內(nèi)存,就沒必要用聚簇索引。
- 插入速度嚴重依賴于插入順序,按主鍵的順序插入是最快的。
- 更新操作代價很高,因為每個被更新的行都會移動到新的位置。
- 當(dāng)插入到某個已滿的頁中,存儲引擎會將該頁分裂成兩個頁面來容納該行,頁分裂會導(dǎo)致表占用更多的磁盤空間。
- 如果行比較稀疏,或者由于頁分裂導(dǎo)致數(shù)據(jù)存儲不連續(xù)時,聚簇索引可能導(dǎo)致全表掃描速度變慢。
邏輯角度
1.普通索引:索引值不唯一
2.唯一索引:唯一索引是不允許任意兩行具有相同索引值的索引,當(dāng)現(xiàn)有數(shù)據(jù)庫中存在重復(fù)鍵值的時候,大多數(shù)數(shù)據(jù)庫不允許將唯一索引和數(shù)據(jù)庫表相關(guān)聯(lián),當(dāng)現(xiàn)有數(shù)據(jù)中存在重復(fù)的鍵值時,大多數(shù)數(shù)據(jù)庫不允許將新創(chuàng)建的唯一索引與表一起保存。數(shù)據(jù)庫還可能防止添加將在表中創(chuàng)建重復(fù)鍵值的新數(shù)據(jù)。例如,如果在employee表中職員的姓(lname)上創(chuàng)建了唯一索引,則任何兩個員工都不能同姓。
3.主鍵索引:數(shù)據(jù)庫中經(jīng)常有一列或幾列的組合,其值能唯一標(biāo)識表中的每一行,該列稱為主鍵。在數(shù)據(jù)庫關(guān)系圖中表為主鍵自動創(chuàng)建主鍵索引,主鍵索引是唯一索引的特定類型,該索引要求主鍵中的每個值都唯一。當(dāng)在查詢中使用主鍵索引時,它還允許對數(shù)據(jù)的快速訪問。
4.空間索引
主鍵和唯一索引的區(qū)別:
1.一個表可以有多個唯一索引,而主鍵只能有一個
2.主鍵可以作為其它表的外鍵
3.主鍵不可以為null,而唯一索引可以為null
主鍵就是聚焦索引”這是極端錯誤的,是對聚焦索引的一種浪費。
主鍵并不一定是聚集索引,只是在SQL SERVER中,未明確指出的情況下,默認將主鍵定義為聚集,而ORACLE中則默認是非聚集
其它索引
1.聯(lián)合索引:又叫復(fù)合索引,Mysql從左到右使用索引中的字段,一個查詢可以只使用索引的一部分,但必須是最左側(cè)的部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3種組合進行查找,但不支持 b,c進行查找 .當(dāng)最左側(cè)字段是常量引用時,索引就十分有效。符合最左原則
聯(lián)合索引實現(xiàn):每個節(jié)點含有多個關(guān)鍵字,排序時按照多個關(guān)鍵字的順序進行排序。而這個順序就是你創(chuàng)建索引時候的順序
如果你經(jīng)常要用到多個字段的多條件查詢,可以考慮建立聯(lián)合索引,建立了一個聯(lián)合索引就相當(dāng)于建立了多個索引
聯(lián)合索引sql會先過濾出last_name符合條件的記錄,在其基礎(chǔ)上再過濾first_name符合條件的記錄。那如果我們分別在last_name和first_name上創(chuàng)建兩個列索引,mysql的處理方式就不一樣了,它會選擇一個最嚴格的索引來進行檢索,可以理解為檢索能力最強的那個索引來檢索,另外一個利用不上了,這樣效果就不如多列索引了。雖然此時有了兩個單列索引,但 MySQL 只能用到其中的那個它認為似乎是最有效率的單列索引。如果經(jīng)常使用單獨一列作為查詢條件,那么應(yīng)該使用單列索引。(如有兩個單列索引a、b,查詢的時候只用a或只用b)。
多列建索引比對每個列分別建索引更有優(yōu)勢,因為索引建立得越多就越占磁盤空間,在更新數(shù)據(jù)的時候速度會更慢。另外建立多列索引時,順序也是需要注意的,應(yīng)該將嚴格的索引放在前面,這樣篩選的力度會更大,效率更高
2.覆蓋索引:只需要通過輔助索引就可以獲取查詢的信息,而無需再通過聚集索引查詢具體的記錄信息
由于覆蓋索引不包含整行的記錄,因此它的大小遠小于聚集索引
比較適合做一些統(tǒng)計操作
索引的創(chuàng)建
在表上創(chuàng)建一個簡單的索引,允許使用重復(fù)的值
CREATE INDEX index_name
ON table_name (column_name)
在表上創(chuàng)建一個唯一的索引。唯一的索引意味著兩個行不能擁有相同的索引值。
CREATE UNIQUE INDEX index_name
ON table_name (column_name)
假如您希望索引不止一個列,您可以在括號中列出這些列的名稱,用逗號隔開:
CREATE INDEX PersonIndex
ON Person (LastName, FirstName)
創(chuàng)建索引還可以用alter實現(xiàn)
InnoDB按照主鍵進行聚集,如果沒有定義主鍵,InnoDB會試著使用唯一的非空索引來代替。如果沒有這種索引,InnoDB就會定義隱藏的主鍵(6個字節(jié))然后在上面進行聚集。mysql不能手動創(chuàng)建聚集索引。
主鍵索引是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創(chuàng)建主鍵索引
索引的實現(xiàn)
一般來說,索引本身也很大,不可能全部存儲在內(nèi)存中,因此索引往往以索引文件的形式存儲的磁盤上。這樣的話,索引查找過程中就要產(chǎn)生磁盤I/O消耗,相對于內(nèi)存存取,I/O存取的消耗要高幾個數(shù)量級,而B+Tree的高度低(多叉樹),可以減少I/O次數(shù)
InnoDB(聚簇索引)的數(shù)據(jù)文件本身就是索引文件(索引和數(shù)據(jù)存放在一個文件idb)。從上文知道,MyISAM(非聚簇索引)索引文件(MYI)和數(shù)據(jù)文件(MYD)是分離的,索引文件僅保存數(shù)據(jù)記錄的地址。
mysql中每個表都有一個聚簇索引(clustered index ),除此之外的表上的每個非聚簇索引都是二級索引(普通索引、唯一索引),又叫輔助索引(secondary indexes)。
實現(xiàn)區(qū)別
MyISAM引擎使用B+Tree作為索引結(jié)構(gòu),葉結(jié)點的data域存放的是數(shù)據(jù)記錄的地址。MyISAM的索引方式也叫做“非聚集”的。
MyISAM左圖為主索引,右圖為輔助索引(二級索引),兩者在結(jié)構(gòu)上沒什么區(qū)別,都是B+樹。
雖然InnoDB也使用B+Tree作為索引結(jié)構(gòu),但具體實現(xiàn)方式卻與MyISAM截然不同。
InnoDB左圖為主索引、右圖為輔助索引,輔助索引結(jié)構(gòu)也是B+樹
第一個重大區(qū)別是InnoDB的數(shù)據(jù)文件本身就是索引文件。從上文知道,MyISAM索引文件和數(shù)據(jù)文件是分離的,索引文件僅保存數(shù)據(jù)記錄的地址。而在InnoDB中,表數(shù)據(jù)文件本身就是按B+Tree組織的一個索引結(jié)構(gòu),這棵樹的葉結(jié)點data域保存了完整的數(shù)據(jù)記錄。這個索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引。
第二個與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。
這里以英文字符的ASCII碼作為比較準則(排序)。聚集索引這種實現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。
由于實際的數(shù)據(jù)頁只能按照一顆B+樹進行排序,因此每張表只能有一個聚集索引。
SQL語句的執(zhí)行順尋
from--where--group by--having--select--order by
Mysql中查看索引
使用“執(zhí)行過程”EXPLAIN,查看索引使用情況,查詢的覆蓋行數(shù)等
EXPLAIN SELECT * FROM user WHERE id = 10
B樹和紅黑樹
B樹主要是保證只有少數(shù)的磁盤訪問(io次數(shù)少),解決數(shù)據(jù)結(jié)構(gòu)不在主存中的數(shù)據(jù)存儲問題。高度低。某一個節(jié)點可以看做一個磁盤塊,里面含有指向下一個磁盤塊的指針。
關(guān)鍵嗎就是上圖磁盤塊中的數(shù)字
B樹從最后一層開始插入,涉及到節(jié)點的分裂
一棵含n個結(jié)點的B樹的高度也為O(logn),但可能比一棵紅黑樹的高度小許多,應(yīng)為它的分支因子比較大。所以,B樹可以在O(logn)時間內(nèi),實現(xiàn)各種如插入(insert),刪除(delete)等動態(tài)集合操作。
“階”定義為一個節(jié)點的子節(jié)點數(shù)目的最大值(非根節(jié)點關(guān)鍵字個數(shù)m/2向上取整-m-1個)
B+樹
只有葉節(jié)點存數(shù)據(jù),非葉節(jié)點都只是下層節(jié)點最大值的復(fù)寫。葉子節(jié)點間多了指針,使得范圍查找變得高效(如上圖查找20到65)
紅黑樹:
性質(zhì)1. 節(jié)點是紅色或黑色。
性質(zhì)2. 根是黑色。
性質(zhì)3. 所有葉子都是黑色(葉子是NIL節(jié)點,空節(jié)點)。
性質(zhì)4. 每個紅色節(jié)點的兩個子節(jié)點都是黑色。
性質(zhì)5. 從任一節(jié)點到其每個葉子的所有簡單路徑 都包含相同數(shù)目的黑色節(jié)點。
在進行紅黑樹的構(gòu)造的時候,為了滿足第5點,則必須每次插入的節(jié)點顏色預(yù)設(shè)為紅色,插入后,有可能會導(dǎo)致4不滿足,然后進行節(jié)點調(diào)整。所以如果是構(gòu)造出來的,一般來說,不會有節(jié)點全黑的紅黑樹
查找、插入、刪除等操作的時間復(fù)雜度為O(logn), 且最多旋轉(zhuǎn)三次
紅黑是用非嚴格的平衡來換取增刪節(jié)點時候旋轉(zhuǎn)次數(shù)的降低,任何不平衡都會在三次旋轉(zhuǎn)之內(nèi)解決,而AVL是嚴格平衡樹,因此在增加或者刪除節(jié)點的時候,根據(jù)不同情況,旋轉(zhuǎn)的次數(shù)比紅黑樹要多。所以紅黑樹的插入效率更高!!!
不能有連續(xù)2個的紅節(jié)點,紅黑樹也是二叉查找樹
紅黑樹的平衡性:最差情況,一棵子樹全是黑色,一棵子樹一紅一黑····,高度最多差一倍(保證黑色數(shù)量相同)
紅黑樹插入時,插入節(jié)點的叔叔是黑節(jié)點:也是類似于avl樹中的單旋轉(zhuǎn),雙旋轉(zhuǎn),并改變著色;插入節(jié)點的叔叔是紅節(jié)點:直接重新著色,并再繼續(xù)向上調(diào)整
紅黑樹某一結(jié)點,如果只有一個兒子(如左),那么該結(jié)點為黑結(jié)點且兒子為紅結(jié)點,若該結(jié)點為紅結(jié)點,則朝右結(jié)點(沒有)方向沒有黑結(jié)點,朝左結(jié)點方向有一個黑結(jié)點,導(dǎo)致不平衡
刪除一個黑色葉結(jié)點時需要較復(fù)雜的調(diào)整,(刪除非葉結(jié)點情況,可以從葉結(jié)點找一個跟該結(jié)點替換,從而變成刪除葉結(jié)點的情況)
數(shù)據(jù)庫引擎
InnoDB和MyISAM區(qū)別
Oracle收購sun(sun之前收購了MySQL),發(fā)布的首個版本5.5,默認使用了InnoDB作為存儲引擎,而之前的版本使用MyISAM作為默認。
MyISAM 和 InnoDB的適用場景
MyISAM適合:讀多寫少(1)做很多count 的計算;(2)插入不頻繁,查詢非常頻繁;(3)沒有事務(wù)。
InnoDB適合:寫多讀少(1)可靠性要求比較高,或者要求事務(wù);(2)表更新和查詢都相當(dāng)?shù)念l繁,并且表鎖定的機會比較大的情況。
為什么MyISAM會比Innodb 的查詢速度快
INNODB在做SELECT的時候,要維護的東西比MYISAM引擎多很多;
1)數(shù)據(jù)塊,INNODB要緩存,MYISAM只緩存索引塊,這中間還有換進換出的減少;
2)innodb尋址要映射到塊,再到行,MYISAM 記錄的直接是文件的OFFSET,定位比INNODB要快
3)INNODB還需要維護MVCC一致;雖然你的場景沒有,但他還是需要去檢查和維護MVCC ( Multi-Version Concurrency Control )多版本并發(fā)控制(讀不加鎖,讀寫不沖突。)
(具體看下面Mysql中InnoDB的MVCC)
兩種類型最主要的差別就是Innodb 支持事務(wù)處理與外鍵和行級鎖
1.存儲結(jié)構(gòu)
每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義;數(shù)據(jù)文件的擴展名為.MYD (MYData);索引文件的擴展名是.MYI (MYIndex)。
InnoDB:.ibd的文件,存儲與該表相關(guān)的數(shù)據(jù)、索引、表的內(nèi)部數(shù)據(jù)字典(表緩存)信息;.frm表結(jié)構(gòu)文件。
2.數(shù)據(jù)導(dǎo)出:
MyISAM只要發(fā)給他們對應(yīng)那表的frm.MYD,MYI的文件,讓他們自己在對應(yīng)版本的數(shù)據(jù)庫啟動就行,而Innodb就需要導(dǎo)出xxx.sql了,因為光給別人文件,受字典數(shù)據(jù)文件的影響,對方是無法使用的。
3.、MyISAM的索引和數(shù)據(jù)是分開的,并且索引是有壓縮的,內(nèi)存使用率就對應(yīng)提高了不少,能加載更多索引。而Innodb是索引和數(shù)據(jù)是緊密捆綁的,沒有使用壓縮從而會造成Innodb占用空間較大
4.MyISAM存儲空間幾乎沒有限制,最多可到64PB,InnoDB最多64TB
5.InnoDB支持事務(wù)(每條sql都是事務(wù),默認配置事務(wù)自動提交)和外鍵,MyISAM不支持
6.對于AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯(lián)合索引。
7.MyISAM:只支持表級鎖,select,update,delete,insert語句都會給表自動加鎖
InnoDB:支持行級鎖,但是InnoDB的行鎖,只是在WHERE的主鍵(唯一索引)是有效的,非主鍵的WHERE都會鎖全表的。對索引加鎖,而不是對數(shù)據(jù)行加鎖,只有當(dāng)查詢條件能使用索引的時候才會使用行級鎖
兩者鎖讀的時候共享鎖、寫的時候排它鎖(可以一起讀,不能一起寫或讀寫)
8.全文索引(通過關(guān)鍵字匹配來查詢)
MyISAM:支持 FULLTEXT類型的全文索引
InnoDB:不支持FULLTEXT類型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。(從5.6開始支持,但不支持中文索引)
9.表的具體行數(shù)
MyISAM:保存有表的總行數(shù),如果select count() from table;會直接取出出該值。
InnoDB:沒有保存表的總行數(shù),如果使用select count() from table;就會遍歷整個表,消耗相當(dāng)大,但是在加了wehre條件后,myisam和innodb處理的方式都一樣。
10.CURD操作
MyISAM:如果執(zhí)行大量的SELECT,MyISAM是更好的選擇。
InnoDB:如果你的數(shù)據(jù)執(zhí)行大量的INSERT或UPDATE,出于性能方面的考慮,應(yīng)該使用InnoDB表。DELETE 從性能上InnoDB更優(yōu),但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除
Mysql其它引擎
Blackhole引擎,它會丟棄所有插入的數(shù)據(jù),不做任何保存。但會記錄日志。
CSV引擎,可以將CSV文件作為MySQL表來處理,可以作為一種數(shù)據(jù)交換機制。
Memory引擎,數(shù)據(jù)存在內(nèi)存中,訪問速度快,重啟后數(shù)據(jù)會丟失。
Merge引擎,是MyISAM的變種,由多個MyISAM表合并而來的虛擬表。
事務(wù)的四大特性
1、原子性(Atomicity):事務(wù)中的全部操作在數(shù)據(jù)庫中是不可分割的,要么全部完成,要么均不執(zhí)行。
2、一致性(Consistency):幾個并行執(zhí)行的事務(wù),其執(zhí)行結(jié)果必須與按某一順序串行執(zhí)行的結(jié)果相一致。事務(wù)必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。多個賬戶錢的總和不變
3、隔離性(Isolation):事務(wù)的執(zhí)行不受其他事務(wù)的干擾,事務(wù)執(zhí)行的中間結(jié)果對其他事務(wù)必須是透明的。(即事務(wù)隔離級別)(轉(zhuǎn)錢時,從其他用戶角度看)
4、持久性(Durability):對于任意已提交事務(wù),系統(tǒng)必須保證該事務(wù)對數(shù)據(jù)庫的改變不被丟失,即使數(shù)據(jù)庫出現(xiàn)故障。
事務(wù)的一致性
1.強一致性:讀操作可以立即讀到提交的更新操作。
2.弱一致性:提交的更新操作,不一定立即會被讀操作讀到,此種情況會存在一個不一致窗口,指的是讀操作可以讀到最新值的一段時間。
3.最終一致性:事務(wù)更新一份數(shù)據(jù),最終一致性保證在沒有其他事務(wù)更新同樣的值的話,最終所有的事務(wù)都會讀到之前事務(wù)更新的最新值。如果沒有錯誤發(fā)生,不一致窗口的大小依賴于:通信延遲,系統(tǒng)負載等。
其他一致性變體還有:
單調(diào)一致性:如果一個進程已經(jīng)讀到一個值,那么后續(xù)不會讀到更早的值。
會話一致性:保證客戶端和服務(wù)器交互的會話過程中,讀操作可以讀到更新操作后的最新值。
事務(wù)的隔離級別
1.臟讀:臟讀是指在一個事務(wù)處理過程里讀取了另一個未提交的事務(wù)中的數(shù)據(jù)。
當(dāng)一個事務(wù)正在多次修改某個數(shù)據(jù),而在這個事務(wù)中這多次的修改都還未提交,這時一個并發(fā)的事務(wù)來訪問該數(shù)據(jù),就會造成兩個事務(wù)得到的數(shù)據(jù)不一致。例如:用戶A向用戶B轉(zhuǎn)賬100元
當(dāng)只執(zhí)行第一條SQL時,A通知B查看賬戶,B發(fā)現(xiàn)確實錢已到賬(此時即發(fā)生了臟讀),而之后無論第二條SQL是否執(zhí)行,只要該事務(wù)不提交,則所有操作都將回滾,那么當(dāng)B以后再次查看賬戶時就會發(fā)現(xiàn)錢其實并沒有轉(zhuǎn)。
2.不可重復(fù)讀:不可重復(fù)讀是指在對于數(shù)據(jù)庫中的某個數(shù)據(jù),一個事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個事務(wù)修改并提交了。不可重復(fù)讀出現(xiàn)的原因就是事務(wù)并發(fā)修改記錄,要避免這種情況,最簡單的方法就是對要修改的記錄加鎖,這回導(dǎo)致鎖競爭加劇,影響性能。另一種方法是通過MVCC可以在無鎖的情況下,避免不可重復(fù)讀。
例如事務(wù)T1在讀取某一數(shù)據(jù),而事務(wù)T2立馬修改了這個數(shù)據(jù)并且提交事務(wù)給數(shù)據(jù)庫,事務(wù)T1再次讀取該數(shù)據(jù)就得到了不同的結(jié)果,發(fā)送了不可重復(fù)讀。
不可重復(fù)讀和臟讀的區(qū)別是,臟讀是某一事務(wù)讀取了另一個事務(wù)未提交的臟數(shù)據(jù),而不可重復(fù)讀則是讀取了前一事務(wù)提交的數(shù)據(jù)。
3,虛讀(幻讀)
在同一個事務(wù)中,同一個查詢多次返回的結(jié)果不一致。事務(wù)A新增了一條記錄,事務(wù)B在事務(wù)A提交前后各執(zhí)行了一次查詢操作,發(fā)現(xiàn)后一次比前一次多了一條記錄。就好像產(chǎn)生幻覺一樣,這就是發(fā)生了幻讀。幻讀是由于并發(fā)事務(wù)增加記錄導(dǎo)致的,這個不能像不可重復(fù)讀通過記錄加鎖解決,因為對于新增的記錄根本無法加鎖。需要將事務(wù)串行化,才能避免幻讀。
幻讀和不可重復(fù)讀都是讀取了另一條已經(jīng)提交的事務(wù)(這點就臟讀不同),所不同的是不可重復(fù)讀查詢的都是同一個數(shù)據(jù)項,而幻讀針對的是一批數(shù)據(jù)整體(比如數(shù)據(jù)的個數(shù))。
MySQL數(shù)據(jù)庫的四種隔離級別(從低到高、為解決并發(fā)事務(wù)問題):
①Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
②Read committed (讀已提交):只有在事務(wù)提交后,其更新結(jié)果才會被其他事務(wù)看見。可避免臟讀的發(fā)生。
③Repeatable read (可重復(fù)讀):在一個事務(wù)中,對于同一份數(shù)據(jù)的讀取結(jié)果總是相同的,無論是否有其他事務(wù)對這份數(shù)據(jù)進行操作,以及這個事務(wù)是否提交。可避免臟讀、不可重復(fù)讀的發(fā)生。
④Serializable (串行化):事務(wù)串行化執(zhí)行,隔離級別最高,犧牲了系統(tǒng)的并發(fā)性。可避免臟讀、不可重復(fù)讀、幻讀的發(fā)生。
在MySQL數(shù)據(jù)庫中,支持上面四種隔離級別,默認的為Repeatable read (可重復(fù)讀);而在Oracle數(shù)據(jù)庫中,只支持Serializable (串行化)級別和Read committed (讀已提交)這兩種級別,其中默認的為Read committed級別。
為什么Mysql能保證失敗回滾
進行事務(wù)處理的時候,MySQL 在開始事務(wù)時會切換到一個延緩操作的狀態(tài),這個狀態(tài)下操作并不都是立即執(zhí)行的(通常情況下語句是立即執(zhí)行的)。而在 commit 時,會將延緩執(zhí)行的操作都執(zhí)行進去,并將狀態(tài)回歸到及時寫入狀態(tài)。同樣的, rollback 時會把延緩寫入的操作拋棄掉,此間申請的鎖釋放掉,并將狀態(tài)回歸到及時寫入狀態(tài)。
執(zhí)行 rollback 的關(guān)鍵在于釋放 申請的鎖 和 回歸及時寫入狀態(tài),而并不是放棄未寫入的操作(你關(guān)心的點在未寫入的操作,然而執(zhí)行與不執(zhí)行 rollback 都沒有操作寫進去,所有你感覺執(zhí)行或不執(zhí)行都沒什么區(qū)別)。
或者是顯示地使用savepoint,rollback到之前設(shè)置的savepoint
數(shù)據(jù)庫完整性約束
數(shù)據(jù)庫完整性約束
數(shù)據(jù)的完整性
約束是用來確保數(shù)據(jù)的準確性和一致性。數(shù)據(jù)的完整性就是對數(shù)據(jù)的準確性和一致性的一種保證。
數(shù)據(jù)完整性(Data Integrity)是指數(shù)據(jù)的精確(Accuracy)和可靠性(Reliability)。
分為以下四類:
- 實體完整性:規(guī)定表的每一行在表中是惟一的實體。
- 域完整性:是指表中的列必須滿足某種特定的數(shù)據(jù)類型約束,其中約束又包括取值范圍、精度等規(guī)定。
- 參照完整性:是指兩個表的主關(guān)鍵字和外關(guān)鍵字的數(shù)據(jù)應(yīng)一致,保證了表之間的數(shù)據(jù)的一致性,防止了數(shù)據(jù)丟失或無意義的數(shù)據(jù)在數(shù)據(jù)庫中擴散。
- 用戶定義的完整性:不同的關(guān)系數(shù)據(jù)庫系統(tǒng)根據(jù)其應(yīng)用環(huán)境的不同,往往還需要一些特殊的約束條件。用戶定義的完整性即是針對某個特定關(guān)系數(shù)據(jù)庫的約束條件,它反映某一具體應(yīng)用必須滿足的語義要求。
與表有關(guān)的約束
主鍵約束(PK)primary key constraint 唯一且不為空
唯一約束(UQ)unique constraint唯一,允許為空,即可以再其中出現(xiàn)null值,但只能出現(xiàn)一次
默認約束(DF)default constraint默認值
檢查約束(CK)check constraint范圍以及格式限制
外鍵約束(FK)foreign key constraint表關(guān)系
數(shù)據(jù)庫調(diào)優(yōu):
MySQL調(diào)優(yōu)分析explain;show status查看服務(wù)器狀態(tài)信息
SQL語句優(yōu)化:
分析:確認程序是否存在查詢不需要的記錄;mysql是否在掃描額外記錄
1、查詢不需要的記錄:使用select語句查詢大量結(jié)果,然后再獲取前N行(如新聞網(wǎng)站,取100條記錄,只顯示前面的10條),這時可以使用limit(limit 1,10;從1開始10行)
2、總是使用SELECT ,對I/O、內(nèi)存消耗較大,不必要時不要這樣。
3、子查詢的性能又比外連接性能慢,盡量用外連接來替換子查詢。
Select from A where exists (select * from B where id>=3000 and A.uuid=B.uuid);
一種簡單的優(yōu)化就是用innerjoin的方法來代替子查詢,查詢語句改為:
Select* from A inner join B using(uuid) where b.uuid>=3000;
4、盡量少排序,排序操作會消耗較多的CPU資源(可以使用索引)
5、對于連續(xù)的數(shù)值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6、切分查詢,將大查詢切分成小查詢,每個查詢功能一樣,只完成一小部分,如果用一個大的語句一次性完成的話,則可能需要一次鎖住很多數(shù)據(jù)、耗盡系統(tǒng)資源、阻塞很多小的但重要的查詢。
索引優(yōu)化
1、建立索引加快查詢性能,優(yōu)先在經(jīng)常搜索的字段上建立索引(where);WHERE子句的查詢條件里使用了比較操作符LIKE前置通配符%(如:LIKE "%ABC"),因為‘%’代表任何字符,%xxx不知道怎么去索引的,所以使用不了索引。只要列中包含有NULL值都將不會被包含在索引中
2、應(yīng)盡量避免在 where 子句中使用 or 來連接條件,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
UNION 操作符用于合并兩個或多個 SELECT 語句的結(jié)果集。請注意,UNION 內(nèi)部的 SELECT 語句必須擁有相同數(shù)量的列。列也必須擁有相似的數(shù)據(jù)類型。不是同一個表也可以union只要列數(shù)相同,UNION 結(jié)果集中的列名總是等于 UNION 中第一個 SELECT 語句中的列名。UNION ALL允許重復(fù)
3、in 和 not in 也要慎用,否則會導(dǎo)致全表掃描,如:
select id from t where num in(1,2,3)
4、有函數(shù)的參數(shù),不使用索引
select * from user where age + 1 =20;
5、應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描
6、在多個列上建立獨立的單列索引大部分情況下不能提高查詢性能,可以使用復(fù)合索引(多列索引),key(name,age,sex)
多列索引有一個特點,即最左前綴(Leftmost Prefixing)。假如有一個多列索引為key(firstname lastname age),當(dāng)搜索條件是以下各種列的組合和順序時,MySQL將使用該多列索引:
firstname,lastname,age
firstname,lastname
firstname
也就是說,相當(dāng)于還建立了key(firstname lastname)和key(firstname)。但是只搜lastname用不到索引
7、由于復(fù)合索引最左前綴匹配,將搜索次數(shù)多的列放到最前列(建立B+樹時從最左字段開始排序,第一個字段相同才排第二個字段,因為查找樹需要一定的順序)
8、盡量選擇小而簡單的數(shù)據(jù)類型做索引,減少磁盤空間
9、有時候需要索引很長的字符列,這會讓索引變得大且慢。一個方式是使用哈希索引,另一個是使用前綴索引,即索引開始的部分字符串,這樣可以節(jié)約索引空間,提高效率。但這樣會降低索引的選擇性(不重復(fù)的索引值/記錄總數(shù))。索引的選擇性越高則查詢效率越高,唯一索引的選擇性是1,性能是最好的。一般情況,某個前綴的選擇性也是足夠高的。
數(shù)據(jù)庫表結(jié)構(gòu)優(yōu)化
選擇合適的數(shù)據(jù)類型
數(shù)據(jù)類型越小越好:盡量使用可以正確存儲數(shù)據(jù)的最小數(shù)據(jù)類型(tinyint,占用更少的磁盤、內(nèi)存、cpu緩存);tinyint占1字節(jié),int占4字節(jié)
簡單就好:如整型比字符操作代價更低(用整型存儲ip地址)
避免NULL:最好指定列為NOT NULL,因為NULL更難優(yōu)化,使用的索引更復(fù)雜
不要設(shè)計太多列:減少不必要的列
適度冗余,減少join關(guān)聯(lián)查詢
適當(dāng)拆分,水平拆分、垂直拆分
選擇合適的字符編碼:如果我們可以確定不需要存放多種語言,就沒必要非得使用UTF8或者其他UNICODE字符類型,這回造成大量的存儲空間浪費
MySQL配置文件優(yōu)化
mysql的配置文件名為my.cnf(window為my.ini),不同情況下配置文件參數(shù)設(shè)置也不相同,應(yīng)該根據(jù)具體場景調(diào)優(yōu)。
InnoDB中最重要的選項是:
innodb_buffer_pool_size:緩存用戶表(實際數(shù)據(jù)row)及索引數(shù)據(jù)的最主要緩存空間,對 Innodb 整體性能影響也最大,默認為8MB,建議設(shè)為內(nèi)存的70%~80%(MyISAM只緩存索引)
innodb_log_file_size:日志文件大小,默認為48MB,應(yīng)該調(diào)大,至少有幾百MB
硬件優(yōu)化:
CPU的選擇
最好的選擇是核心數(shù)多并且主頻高的。但是有時考慮成本問題,可以參考以下情況:
如果不是密集型的查詢,優(yōu)先選頻率高的,而不是數(shù)量多的
如果是密集型的、高并發(fā)的查詢,比如秒殺等活動,優(yōu)先選更多的cpu
因為一條sql語句只能在一個cpu上執(zhí)行
內(nèi)存的選擇
內(nèi)存并不是容量越大,性能提升越明顯。如果內(nèi)存大小已經(jīng)超過了總數(shù)據(jù)量的大小,那么即使再增加內(nèi)存,系能提升也不會特別明顯。
內(nèi)存頻率選擇cpu支持的最高的頻率,品牌、型號、規(guī)格等要一致。
磁盤配置和選擇
各種磁盤性能比較:
PCIe > SSD > Raid10 > 磁盤 > 網(wǎng)絡(luò)存儲
各種磁盤的特點和應(yīng)用:
傳統(tǒng)硬盤:需要考慮存儲容量、傳輸速度、訪問時間、主軸轉(zhuǎn)速、物理尺寸等參數(shù)
raid增加傳統(tǒng)硬盤性能:主服務(wù)器建議用raid10,從服務(wù)器可以raid0(raid0:數(shù)據(jù)等量放置在2塊磁盤中,raid1:讓同一份數(shù)據(jù)完整保存在兩塊磁盤)
SSD或者PCIe卡(FusionIO):缺點比傳統(tǒng)硬盤更容易壞
SSD應(yīng)用場景:適用于存在大量隨機I/O場景(SSD隨機I/O快)、適用于解決單線程負載的I/O瓶頸(用在從服務(wù)器上,適用于讀的場景,頻繁寫會減少使用壽命)
網(wǎng)絡(luò)存儲場景(NAS、SAN):數(shù)據(jù)庫備份
操作系統(tǒng)
合理配置操作系統(tǒng)參數(shù),選擇合適的文件系統(tǒng)
加緩存redis
先讀寫分離、再垂直拆分、再水平拆分
分庫:根據(jù)業(yè)務(wù)邏輯垂直拆分
分表:
縱向分表(常見為忙閑分表)
單數(shù)據(jù)表字段過多,可將頻繁更新的整數(shù)數(shù)據(jù)與非頻繁更新的字符串?dāng)?shù)據(jù)切分 ? 范例 user表 ,個人簡介,地址,QQ號,聯(lián)系方式,頭像 這些字段為字符 串類型,更新請求少; 最后登錄時間,在線時常,訪問次數(shù),信件數(shù)這些字段為整數(shù)型字段,更新頻繁,可以將后面這些更新頻繁的字段獨立拆出一張數(shù)據(jù)表,表內(nèi)容變少,索引結(jié)構(gòu)變少,讀寫請求變快。
橫向切表
等分切表,如哈希切表或其他基于對某數(shù)字取余的切表(USERID奇數(shù)、偶數(shù))。等分切表的優(yōu)點是負 載很方便的分布到不同服務(wù)器;缺點是當(dāng)容量繼續(xù)增加時無法方便的擴容,需要重新進行數(shù)據(jù)的切分或轉(zhuǎn)表。而且一些關(guān)鍵主鍵不易處理。
遞增切表,比如每1kw用戶開一個新表,優(yōu)點是可以適應(yīng)數(shù)據(jù)的自增趨勢; 缺點是往往新數(shù)據(jù)負載高,壓力分配不平均。
索引的好處:
創(chuàng)建索引可以大大提高數(shù)據(jù)庫系統(tǒng)的查詢性能、將隨機I/O變?yōu)轫樞騃/O(磁盤順序)。
- 大大減少了服務(wù)器需要掃描的數(shù)據(jù)量;
- 幫助服務(wù)器避免進行排序和創(chuàng)建臨時表;
- 將隨機 I/O 變?yōu)轫樞?I/O。
- 提高了查詢的速度
索引的代價
建立索引需要付出的代價 建立索引的目的是加快對表中記錄的查找或排序。但是為表設(shè)置索引是要付出代價的:這個代價有幾個個方面
a) 索引需要占物理空間 除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。
b) 創(chuàng)建索引和維護索引要耗費時間 這種時間隨著數(shù)據(jù)量的增加而增加。
c) 降低維護速度 當(dāng)對表中的數(shù)據(jù)進行增加、刪除和修改的時候,索引也要動態(tài)的維護,這樣就降低了數(shù)據(jù)的維護速度,同樣降低了效率。
判斷是否應(yīng)該建索引的條件
1、較頻繁的作為查詢條件的字段應(yīng)該創(chuàng)建索引
2、唯一性太差的字段不適合單獨創(chuàng)建索引,即使頻繁作為查詢條件
3、增、刪、改操作較多的數(shù)據(jù)庫字段不適合建索引(加了索引后update會增加耗時)
4、表記錄比較少,例如一兩千條甚至只有幾百條記錄的表,沒必要建索引,讓查詢做全表掃描就好了。
5、性別字段(只有男、女)不適合建索引,性別字段的選擇性低,使用索引查找還不如遍歷表的效率高。最多只能少檢索一半,但索引的額外開銷更大,得不償失
數(shù)據(jù)庫的悲觀鎖和樂觀鎖
一、悲觀鎖
1、排它鎖,當(dāng)事務(wù)在操作數(shù)據(jù)時把這部分數(shù)據(jù)進行鎖定,直到操作完畢后再解鎖,其他事務(wù)操作才可操作該部分數(shù)據(jù)。這將防止其他進程讀取或修改表中的數(shù)據(jù)。
2、實現(xiàn):大多數(shù)情況下依靠數(shù)據(jù)庫的鎖機制實現(xiàn)
二、樂觀鎖
1、如果有人在你之前更新了,你的更新應(yīng)當(dāng)是被拒絕的,可以讓用戶重新操作。
2、實現(xiàn):大多數(shù)基于數(shù)據(jù)版本(Version)記錄機制實現(xiàn)
具體可通過給表加一個版本號或時間戳字段實現(xiàn),當(dāng)讀取數(shù)據(jù)時,將version字段的值一同讀出,數(shù)據(jù)每更新一次,對此version值加一。當(dāng)我們提交更新的時候,判斷當(dāng)前版本信息與第一次取出來的版本值大小,如果數(shù)據(jù)庫表當(dāng)前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數(shù)據(jù),拒絕更新,讓用戶重新操作。
并發(fā)量很高的話,建議使用悲觀鎖,否則的話就使用樂觀鎖
Mysql頁鎖:
頁級:引擎 BDB。
表級:引擎 MyISAM , 理解為鎖住整個表,可以同時讀,寫不行
行級:引擎 INNODB , 單獨的一行記錄加鎖
表級,直接鎖定整張表,在你鎖定期間,其它進程無法對該表進行寫操作。如果你是寫鎖,則其它進程則讀也不允許
行級,僅對指定的記錄進行加鎖,這樣其它進程還是可以對同一個表中的其它記錄進行操作。
頁級,表級鎖速度快,但沖突多,行級沖突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。
Mysql意向鎖:
①在MySQL中有表鎖,
LOCK TABLE my_tabl_name READ; 用讀鎖鎖表,會阻塞其他事務(wù)修改表數(shù)據(jù)。
LOCK TABLE my_table_name WRITe; 用寫鎖鎖表,會阻塞其他事務(wù)讀和寫。
②Innodb引擎又支持行鎖,行鎖分為
共享鎖(讀鎖),一個事務(wù)對一行的共享只讀鎖。
排它鎖,一個事務(wù)對一行的排他讀寫鎖。
③這兩中類型的鎖共存的問題
考慮這個例子:
事務(wù)A鎖住了表中的一行,讓這一行只能讀,不能寫。
之后,事務(wù)B申請整個表的寫鎖。
如果事務(wù)B申請成功,那么理論上它就能修改表中的任意一行,這與A持有的行鎖是沖突的。
數(shù)據(jù)庫需要避免這種沖突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。
數(shù)據(jù)庫要怎么判斷這個沖突呢?
step1:判斷表是否已被其他事務(wù)用表鎖鎖表
step2:判斷表中的每一行是否已被行鎖鎖住。
注意step2,這樣的判斷方法效率實在不高,因為需要遍歷整個表。
于是就有了意向鎖。
在意向鎖存在的情況下,事務(wù)A必須先申請表的意向共享鎖,成功后再申請一行的行鎖。
在意向鎖存在的情況下,上面的判斷可以改成
step1:不變
step2:發(fā)現(xiàn)表上有意向共享鎖,說明表中有些行被共享行鎖鎖住了,因此,事務(wù)B申請表的寫鎖會被阻塞。
意向鎖是為了提高封鎖子系統(tǒng)的效率。
注意:申請意向鎖的動作是數(shù)據(jù)庫完成的,就是說,事務(wù)A申請一行的行鎖的時候,數(shù)據(jù)庫會自動先開始申請表的意向鎖,不需要我們程序員使用代碼來申請。
MySQL中InnoDB的MVCC
MVCC的原理與copyonwrite類似,全稱是Multi-Version Concurrent Control,即多版本并發(fā)控制。MVCC允許數(shù)據(jù)具有多個版本,這個版本可以是時間戳或者是全局遞增的事務(wù)ID,在同一個時間點,不同的事務(wù)看到的數(shù)據(jù)是不同的。
由于在update操作提交之前,不能影響已有數(shù)據(jù)的一致性,所以不會改變舊的數(shù)據(jù),update操作會被拆分成insert + delete。需要標(biāo)記刪除舊的數(shù)據(jù),insert新的數(shù)據(jù)。只有update提交之后,才會影響后續(xù)的讀操作。而對于讀操作而且,只能讀到在其之前的所有的寫操作,正在執(zhí)行中的寫操作對其是不可見的。(讀不加鎖,讀寫不沖突)
innodb會為每一行添加兩個字段,分別表示該行創(chuàng)建的版本和刪除的版本,填入的是事務(wù)的版本號,這個版本號隨著事務(wù)的創(chuàng)建不斷遞增。在repeated read的隔離級別下,具體各種數(shù)據(jù)庫操作的實現(xiàn):
select:滿足以下兩個條件能夠查詢成功:(1)該行的創(chuàng)建版本號小于等于當(dāng)前版本號,用于保證在select操作之前所有的操作已經(jīng)執(zhí)行落地。(2)該行的刪除版本號大于當(dāng)前版本或者為空。刪除版本號大于當(dāng)前版本意味著有一個并發(fā)事務(wù)將該行刪除了。
insert:將新插入的行的創(chuàng)建版本號設(shè)置為當(dāng)前系統(tǒng)的版本號。
delete:將要刪除的行的刪除版本號設(shè)置為當(dāng)前系統(tǒng)的版本號。
update:不執(zhí)行原地update(相當(dāng)于寫操作),而是轉(zhuǎn)換成insert + delete。將舊行的刪除版本號設(shè)置為當(dāng)前版本號,并將新行insert同時設(shè)置創(chuàng)建版本號為當(dāng)前版本號。
其中,寫操作(insert、delete和update)執(zhí)行時,需要將系統(tǒng)版本號遞增。
由于舊數(shù)據(jù)并不真正的刪除,所以必須對這些數(shù)據(jù)進行清理,innodb會開啟一個后臺線程執(zhí)行清理工作,具體的規(guī)則是將刪除版本號小于當(dāng)前系統(tǒng)版本的行刪除,這個過程叫做purge。
通過MVCC很好的實現(xiàn)了事務(wù)的隔離性,可以達到repeated read級別,要實現(xiàn)serializable還必須加鎖。
MVCC和樂觀鎖區(qū)別
在數(shù)據(jù)庫中,并發(fā)控制是指在多個用戶/進程/線程同時對數(shù)據(jù)庫進行操作時,如何保證事務(wù)的一致性和隔離性的,同時最大程度地并發(fā)。
當(dāng)多個用戶/進程/線程同時對數(shù)據(jù)庫進行操作時,會出現(xiàn)3種沖突情形:
讀-讀,不存在任何問題讀-寫,有隔離性問題,可能遇到臟讀(會讀到未提交的數(shù)據(jù)) ,幻影讀等。寫-寫,可能丟失更新要解決沖突,一種辦法是是鎖,即基于鎖的并發(fā)控制,比如2PL,這種方式開銷比較高,而且無法避免死鎖。
多版本并發(fā)控制(MVCC)是一種用來解決讀-寫沖突的無鎖并發(fā)控制,也就是為事務(wù)分配單向增長的時間戳,為每個修改保存一個版本,版本與事務(wù)時間戳關(guān)聯(lián),讀操作只讀該事務(wù)開始前的數(shù)據(jù)庫的快照。 這樣在讀操作不用阻塞寫操作,寫操作不用阻塞讀操作的同時,避免了臟讀和不可重復(fù)讀
樂觀并發(fā)控制(OCC)是一種用來解決寫-寫沖突的無鎖并發(fā)控制,認為事務(wù)間爭用沒有那么多,所以先進行修改,在提交事務(wù)前,檢查一下事務(wù)開始后,有沒有新提交改變,如果沒有就提交,如果有就放棄并重試。樂觀并發(fā)控制類似自旋鎖。樂觀并發(fā)控制適用于低數(shù)據(jù)爭用,寫沖突比較少的環(huán)境。多版本并發(fā)控制可以結(jié)合基于鎖的并發(fā)控制來解決寫-寫沖突,即MVCC+2PL,也可以結(jié)合樂觀并發(fā)控制來解決寫-寫沖突。
Mysql5.7的新特性
MySQL 5.7版本提供了更為簡單SSL安全訪問配置,并且默認連接就采用SSL的加密方式
MySQL數(shù)據(jù)庫從5.7.8版本開始,也提供了對JSON的支持。
generated column是MySQL 5.7引入的新特性,所謂generated column,就是數(shù)據(jù)庫中這一列由其他列計算而得。
不支持子查詢中排序
范式
第一范式1NF的定義為:符合1NF的關(guān)系中的每個屬性都不可再分,1NF是所有關(guān)系型數(shù)據(jù)庫的最基本要。
2NF在1NF的基礎(chǔ)之上,消除了非主屬性對于碼的部分函數(shù)依賴。
碼:設(shè) K 為某表中的一個屬性或?qū)傩越M,若除 K 之外的所有屬性都完全函數(shù)依賴于 K(這個“完全”不要漏了),那么我們稱 K 為候選碼,簡稱為碼。在實際中我們通常可以理解為:假如當(dāng) K 確定的情況下,該表除 K 之外的所有屬性的值也就隨之確定,那么 K 就是碼。一張表中可以有超過一個碼。
部分函數(shù)依賴:依賴于碼的一部分(其中的某幾個)
非主屬性:包含在任何一個碼中的屬性成為主屬性。
3NF在2NF的基礎(chǔ)之上,消除了非主屬性對于碼的傳遞函數(shù)依賴。
BCNF范式:在 3NF 的基礎(chǔ)上消除主屬性對于碼的部分與傳遞函數(shù)依賴
(https://www.zhihu.com/question/24696366)
反范式是通過增加冗余數(shù)據(jù)或數(shù)據(jù)分組來提高數(shù)據(jù)庫讀性能的過程。在某些情況下, 反范式有助于掩蓋關(guān)系型數(shù)據(jù)庫軟件的低效。關(guān)系型的范式數(shù)據(jù)庫即使做過優(yōu)化, 也常常會帶來沉重的訪問負載。
JDBC的參數(shù)
數(shù)據(jù)庫系統(tǒng)設(shè)計步驟
數(shù)據(jù)庫設(shè)計的過程(六個階段)
1.需求分析階段
準確了解與分析用戶需求(包括數(shù)據(jù)與處理)
是整個設(shè)計過程的基礎(chǔ),是最困難、最耗費時間的一步
2.概念結(jié)構(gòu)設(shè)計階段
是整個數(shù)據(jù)庫設(shè)計的關(guān)鍵
通過對用戶需求進行綜合、歸納與抽象,形成一個獨立于具體DBMS的概念模型(DBMS數(shù)據(jù)庫管理系統(tǒng),如MySQL)
3.邏輯結(jié)構(gòu)設(shè)計階段
將概念結(jié)構(gòu)轉(zhuǎn)換為某個DBMS所支持的數(shù)據(jù)模型,對其進行優(yōu)化
4.數(shù)據(jù)庫物理設(shè)計階段
為邏輯數(shù)據(jù)模型選取一個最適合應(yīng)用環(huán)境的物理結(jié)構(gòu)(包括存儲結(jié)構(gòu)和存取方法)
5.數(shù)據(jù)庫實施階段
運用DBMS提供的數(shù)據(jù)語言、工具及宿主語言,根據(jù)邏輯設(shè)計和物理設(shè)計的結(jié)果
建立數(shù)據(jù)庫,編制與調(diào)試應(yīng)用程序,組織數(shù)據(jù)入庫,并進行試運行
6.數(shù)據(jù)庫運行和維護階段
數(shù)據(jù)庫應(yīng)用系統(tǒng)經(jīng)過試運行后即可投入正式運行。
在數(shù)據(jù)庫系統(tǒng)運行過程中必須不斷地對其進行評價、調(diào)整與修改
數(shù)據(jù)庫各級模式的形成過程
1.需求分析階段:綜合各個用戶的應(yīng)用需求
2.概念設(shè)計階段:形成獨立于機器特點,獨立于各個DBMS產(chǎn)品的概念模式(E-R圖,實體-聯(lián)系圖)
3.邏輯設(shè)計階段:首先將E-R圖轉(zhuǎn)換成具體的數(shù)據(jù)庫產(chǎn)品支持的數(shù)據(jù)模型,如關(guān)系模型,形成數(shù)據(jù)庫邏輯模式;然后根據(jù)用戶處理的要求、安全性的考慮,在基本表的基礎(chǔ)上再建立必要的視圖(View),形成數(shù)據(jù)的外模式(將E-R轉(zhuǎn)換成表,根據(jù)范式設(shè)計表,表結(jié)構(gòu)設(shè)計盡量簡單、小)
4.物理設(shè)計階段:根據(jù)DBMS特點和處理的需要,進行物理存儲安排,建立索引,形成數(shù)據(jù)庫內(nèi)模式