1.索引是怎么實(shí)現(xiàn)的嗎?
1.索引是什么,索引是由什么來實(shí)現(xiàn)的?
索引是為了加速對(duì)表中數(shù)據(jù)的檢索而創(chuàng)建的一種分散存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu),索引是有存儲(chǔ)引擎來實(shí)現(xiàn)的。
2.為什么用索引
索引能極大的減少存儲(chǔ)引擎需要掃描的數(shù)據(jù)量;索引可以把隨機(jī)IO變成順序IO;索引可以幫助我們?cè)谶M(jìn)行分組、排序的時(shí)候,避免使用臨時(shí)表
3.索引為什么使用B+Tree
動(dòng)態(tài)展示數(shù)據(jù)結(jié)構(gòu)的網(wǎng)站: https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
首先,我們會(huì)想到用二叉樹來存儲(chǔ)數(shù)據(jù),但是,二叉樹會(huì)造成整個(gè)樹的深度過大,通過根節(jié)點(diǎn)查找數(shù)據(jù),會(huì)多走很多步。然后就會(huì)考慮平衡二叉樹,但是平衡二叉樹每個(gè)節(jié)點(diǎn)只有兩個(gè)子節(jié)點(diǎn),所以樹的深度過大,而且每個(gè)磁盤塊保存的數(shù)據(jù)量太小了。而B樹就很好的解決了這兩個(gè)問題(mysql使用的B+樹原理跟B樹差不多)。
B+樹和B樹的區(qū)別是:
B+樹關(guān)鍵字搜索采用閉合區(qū)間
B+樹非葉子節(jié)點(diǎn)不保存數(shù)據(jù)信息,只保存關(guān)鍵字和子節(jié)點(diǎn)的引用,數(shù)據(jù)保存在葉子節(jié)點(diǎn)
B+樹葉子節(jié)點(diǎn)是順序排列的,并且相鄰節(jié)點(diǎn)具有順序引用的關(guān)系
B+樹對(duì)比B樹有哪些優(yōu)勢(shì):
擁有B樹所有的優(yōu)勢(shì)
掃庫(kù)/表能力更強(qiáng)
磁盤讀寫能力更強(qiáng)
排序能力更強(qiáng)
4.B+樹在存儲(chǔ)引擎中的體現(xiàn)形式
InnoDb:在InnDb中的索引和數(shù)據(jù)都存在以
.idb為后綴名的文件中,所有數(shù)據(jù)都存在以主鍵索引為根節(jié)點(diǎn)或者枝節(jié)點(diǎn)的B+樹的葉子節(jié)點(diǎn)中(即便建表時(shí)沒有創(chuàng)建主鍵,InnoDB也會(huì)自動(dòng)創(chuàng)建隱性主鍵),其他的索引形成的B+樹的葉子節(jié)點(diǎn)都存的是主鍵MyISAM:索引存在
.myi文件中,數(shù)據(jù)存在.myd文件中,各個(gè)索引形成的B+樹的葉子節(jié)點(diǎn)都是數(shù)據(jù)的物理地址
5.索引知識(shí)補(bǔ)充
列的離散性(區(qū)分度):每一列的不同數(shù)據(jù)越多,它的離散性也就越好,如果離散性不好,創(chuàng)建的索引在搜索時(shí),B+樹可選擇分支太多,優(yōu)化器可能就會(huì)使用全表掃描
最左匹配原則:對(duì)索引中關(guān)鍵字進(jìn)行比對(duì),一定是從左向右且不可跳過
聯(lián)合索引注意點(diǎn):1.經(jīng)常使用的列靠左放,2.區(qū)分度高的列靠左放 3.寬度小的列靠左放
覆蓋索引:如果查詢的列可以通過索引中的關(guān)鍵字直接返回(不需要回表),那么就是覆蓋索引
select * from user where name like 'abc%',如果那么name字段有索引,這條語句也不一定會(huì)用到索引,因?yàn)閚ame字段有可能因?yàn)閰^(qū)分度不高,優(yōu)化器通過全表掃描>,<可以用到索引,not in,!=用不到,order by可以用到聯(lián)合索引中,精確匹配最左列范圍匹配另一列可以用到索引 ,如:[age+name], 條件是:
age=28 and name like 'abcd%'聯(lián)合索引中,范圍匹配某個(gè)列,其右邊的所以的列都用不到索引,如[age+name],條件是:
age > 20 and name = 'abcde'
2.
1.mysql的體系結(jié)及查詢流程
客戶端->連接池(Connection Poll) ->sql InterFace -> 解析器 -> 優(yōu)化器 ->執(zhí)行器 ->存儲(chǔ)引擎
2.mysql的存儲(chǔ)引擎(插拔式)
csv存儲(chǔ)引擎:應(yīng)用于數(shù)據(jù)的快速導(dǎo)入導(dǎo)出,表直接轉(zhuǎn)成csv文件
archive存儲(chǔ)引擎:應(yīng)用于日志系統(tǒng),大量設(shè)備數(shù)據(jù)采集
memory存儲(chǔ)引擎:數(shù)據(jù)存在內(nèi)存中,數(shù)據(jù)表默認(rèn)只有16M,大多數(shù)應(yīng)用于臨時(shí)表
MyIsam存儲(chǔ)引擎:select count 無需進(jìn)行數(shù)據(jù)的掃描,表級(jí)鎖,不支持事務(wù)
InnoDB:支持事務(wù),行級(jí)鎖,聚集索引(主鍵索引)的方式來存儲(chǔ)數(shù)據(jù),支持外鍵
3.mysql查詢優(yōu)化詳解
mysql客戶端/服務(wù)端通信 :半雙工的通信方式,其常用的連接狀態(tài)(通過 show processlist查看)有:sleep(線程正在等待客戶端發(fā)送數(shù)據(jù)),Query(連接線程正在執(zhí)行查詢),Locked(線程正在等待表鎖釋放),Sorting result(線程正在對(duì)數(shù)據(jù)進(jìn)行排序),Sending data(正在向請(qǐng)求端返回?cái)?shù)據(jù))
查詢緩存 : 完全相同的兩條sql才會(huì)命中緩存,如果涉及的表有任何改變,緩存失效
-
查詢優(yōu)化處理
1.解析sql:通過詞法分析,語法分析將sql語句解析成解析樹
2.預(yù)處理階段:通過mysql的語法規(guī)則進(jìn)一步檢查解析樹的合法性,如:檢查表和列是否存在,解析名字和別民的設(shè)置,進(jìn)行權(quán)限驗(yàn)證
3.查詢優(yōu)化器:找到最優(yōu)的執(zhí)行計(jì)劃,有:使用等價(jià)變換規(guī)則,將可轉(zhuǎn)化的外連接查詢換成內(nèi)連接查詢,優(yōu)化count/min/max等函數(shù),覆蓋索引掃描,子查詢優(yōu)化,提前終止查詢(limit),in的優(yōu)化 等。
查詢執(zhí)行引擎
返回客戶端:增量的返回結(jié)果,開始生成第一條結(jié)果時(shí),mysql就開始往請(qǐng)求方逐步返回
4.如何定位慢sql
業(yè)務(wù)驅(qū)動(dòng)
測(cè)試驅(qū)動(dòng)
慢查詢?nèi)罩?
show variables like 'slow_quer%';來找到慢查詢?nèi)罩镜奈恢?,日志文件中的time:日志的記錄時(shí)間,User@Host:執(zhí)行的用戶及主機(jī),Query_time:查詢的耗時(shí),Lock_time:鎖表時(shí)間,Rows_send:發(fā)送給請(qǐng)求方的條數(shù),Rows_examined:語句掃描的條數(shù),SET timetamp:語句執(zhí)行的時(shí)間戳, select ....執(zhí)行的具體語句。還可以通過mysqldumpslow來分析慢查詢?nèi)罩疚募?/strong>
3. InnoDB事務(wù)/鎖
1.事務(wù)
原子性:最小的工作單元,要么一起調(diào)教成功,要么一起回滾
一致性:事務(wù)中操作的數(shù)據(jù)及狀態(tài)是一致的,即寫入資料的結(jié)果必須完全符合預(yù)定的規(guī)則,不會(huì)因?yàn)槌霈F(xiàn)系統(tǒng)意外等外部原因等造成狀態(tài)不一致
隔離性:一個(gè)事務(wù)所操作的數(shù)據(jù)在提交之前,對(duì)其他事務(wù)的可見性設(shè)置(一般設(shè)為不可見)
持久性:事務(wù)所作的修改就會(huì)永久保存,不會(huì)因?yàn)橄到y(tǒng)意外而導(dǎo)致數(shù)據(jù)丟失
2.事務(wù)并發(fā)造成哪些問題
臟讀:一個(gè)事務(wù)中對(duì)一條記錄進(jìn)行修改,另一個(gè)并發(fā)的事務(wù)查到了這個(gè)修改后的數(shù)據(jù),然后第一個(gè)事務(wù)回滾
不可重復(fù)讀:一個(gè)事務(wù)中第一次查詢的結(jié)果,被并發(fā)的另一個(gè)事務(wù)所修改,第一個(gè)事務(wù)中第二次查詢到修改后的值
幻讀:一個(gè)事務(wù)中查詢了一個(gè)數(shù)據(jù)范圍,并發(fā)的另一個(gè)事務(wù)插入了一條符合這個(gè)范圍的數(shù)據(jù),第一個(gè)事務(wù)再次查詢范圍造成的問題
3.針對(duì)這些問題定義了四種隔離級(jí)別
讀未提交(未解決并發(fā)問題):事務(wù)未提交對(duì)其他事務(wù)是可見的,造成的問題:臟讀
讀提交(解決臟讀問題):一個(gè)事務(wù)開始之后,只能看到自己提交的事務(wù)所作的修改,造成的問題:不可重復(fù)讀
可重復(fù)讀(解決不可重復(fù)讀):在同一個(gè)事務(wù)中不管什么時(shí)候讀取同樣的數(shù)據(jù)結(jié)果是一樣的,造成的問題:幻讀
串行話(解決所有問題):最高的隔離級(jí)別,通過強(qiáng)制事務(wù)的串行執(zhí)行
對(duì)于以上幾種隔離級(jí)別,并發(fā)能力越來越低 對(duì)于InnoDB引擎,在可重復(fù)讀的隔離級(jí)別下,解決了幻讀的問題
4.隔離級(jí)別是通過什么實(shí)現(xiàn)的
通過鎖和MVCC來實(shí)現(xiàn)
5.鎖
鎖是用戶管理不同事務(wù)對(duì)共享資源的并發(fā)訪問
表鎖和行鎖的區(qū)別:
鎖定粒度:表鎖>行鎖
加鎖效率:表鎖>行鎖
沖突概率:表鎖>行鎖
并發(fā)性能:表鎖<行鎖
InnoDB支持行鎖和表鎖(另類的行鎖)
InnoDB的行鎖是通過給索引的索引項(xiàng)加鎖來實(shí)現(xiàn)的,只有通過索引條件進(jìn)行數(shù)據(jù)檢索,InnoDB才會(huì)使用行鎖,否則 InnoDB將使用表鎖(鎖住索引的所有記錄),如:非主鍵索引被鎖住,除了這個(gè)索引被鎖,其對(duì)應(yīng)的主鍵也會(huì)被鎖
鎖的類型:
共享鎖(行鎖):又稱讀鎖(s鎖),多個(gè)事務(wù)對(duì)于同一個(gè)數(shù)據(jù)共享一把鎖,只能讀不能修改,加鎖語句是:在普通搜索后面加上
LOCK IN SHARE MODE排他鎖(行鎖):又稱寫鎖(x鎖),排他鎖不能與其他鎖并存,如果一個(gè)事務(wù)獲取了一個(gè)數(shù)據(jù)的排他鎖,其他事務(wù)不能在獲取到該行數(shù)據(jù)的鎖(排他鎖,共享鎖),只有獲取排他鎖的事務(wù)能對(duì)該行數(shù)據(jù)進(jìn)行讀取和修改(其他事務(wù)讀取的數(shù)據(jù)來自快照)
意向鎖共享鎖(表鎖):又稱 IS鎖,表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入共享鎖,即一個(gè)數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖,意向共享鎖之間是可以互相兼容的
意向鎖排他鎖(表鎖):又稱 IX鎖,表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入排他鎖,即一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖,意向排他鎖之間是可以互相兼容的
意向鎖是InnoDB數(shù)據(jù)操作前自動(dòng)加上去的,不需要用戶干預(yù),其意義:當(dāng)事務(wù)想去鎖表的時(shí)候,可以先判斷意向鎖是否存在,存在則可快速返回該表不能縮表,如果,一個(gè)事務(wù)中一個(gè)數(shù)據(jù)行加了排他鎖,另一個(gè)事務(wù)中的更新條件沒有索引(這時(shí)候就會(huì)鎖表),這時(shí)候這個(gè)事務(wù)就會(huì)別鎖住
自增鎖:針對(duì)自增列自增長(zhǎng)的一個(gè)特殊的表級(jí)別鎖,默認(rèn)值是1,代表連續(xù),事務(wù)未提交ID永久丟失,比如:一個(gè)事務(wù)中插入一條數(shù)據(jù),但是回滾,那么這個(gè)別分配到的ID就會(huì)丟失,不會(huì)被其他事務(wù)用到(除非強(qiáng)制設(shè)置ID)
-
記錄鎖(行鎖的算法):Record Lock 鎖住具體的索引項(xiàng),當(dāng)sql執(zhí)行按照唯一性(主鍵,唯一索引)索引進(jìn)行數(shù)據(jù)的檢索時(shí),查詢條件等值匹配且查詢的數(shù)據(jù)存在時(shí),這時(shí)候sql語句加上的鎖即為Record Lock,即從臨鍵鎖退化為記錄鎖,如:
select * from t where id = 4 for update,數(shù)據(jù)庫(kù)中的數(shù)據(jù)是 1,4,7,10,那么鎖住的是4這條記錄注意點(diǎn):如果id不是主鍵或者唯一索引,那么鎖住的是(1,4](4,7]
間隙鎖(行鎖的算法):Gap Lock 鎖住數(shù)據(jù)不存在的區(qū)間(左開右開),,當(dāng)sql執(zhí)行按照索引進(jìn)行數(shù)據(jù)的檢索時(shí),查詢條件不存在,這時(shí)候sql語句加上的鎖即為Gap Lock,即從臨鍵鎖退化為間隙鎖,間隙鎖只存在于可重復(fù)讀的隔離級(jí)別下如:
select * from t where id > 4 and id <7 for update,數(shù)據(jù)庫(kù)中的數(shù)據(jù)是 1,4,7,10,那么鎖住的是(4,7)臨鍵鎖(行鎖的算法):Next-key Lock ,鎖住記錄+區(qū)間(左開右閉),即鎖住這條記錄的區(qū)間以及下一個(gè)區(qū)間,當(dāng)sql執(zhí)行按照索引進(jìn)行數(shù)據(jù)的檢索時(shí),查詢條件為范圍查找(between,and,<,>等)并有數(shù)據(jù)命中,則此時(shí)sql語句加上的鎖為Next-key Lock,臨鍵鎖 = 間隙鎖+記錄鎖,該算法是為了防止幻讀, 如:
select * from t where id >5 and id <10 for update,數(shù)據(jù)庫(kù)中的數(shù)據(jù)是 1,4,7,10,那么鎖住的是(4,7],(7,10]
6.臟讀/不可重復(fù)讀/幻讀的問題怎么解決
臟讀:加上排他鎖
不可重復(fù)讀:加上共享鎖
幻讀:加上臨鍵鎖
7.死鎖的介紹及避免
一個(gè)事務(wù)中持有A的鎖,等待B的鎖,另一個(gè)事務(wù)中持有B的鎖,等待A的鎖,就造成死鎖
如何避免:
類似的業(yè)務(wù)以固定的順序訪問表和行 ,如:一個(gè)事務(wù)中先扣用戶的錢,在給商家加錢,在另一個(gè)事務(wù)中,也要類似的操作
大事務(wù)拆成小事務(wù)
在同一個(gè)事務(wù)中,盡可能一次鎖定所有需要的的資源
業(yè)務(wù)允許的情況下,降低隔離級(jí)別
為表加上合理的索引
4.MVCC(多版本并發(fā)控制)
1.MVCC是什么
并發(fā)訪問(讀或者寫)數(shù)據(jù)庫(kù)時(shí),對(duì)正在事務(wù)內(nèi)處理的數(shù)據(jù)做多版本的管理,以達(dá)到永用來避免寫操作的堵塞,從而引發(fā)讀操作的并發(fā)問題
2.建表或作插入、修改、查找操作時(shí),做了什么
建表:在創(chuàng)建一個(gè)表的時(shí)候,數(shù)據(jù)庫(kù)會(huì)默認(rèn)創(chuàng)建兩個(gè)隱藏的列 DT_TRX_ID(數(shù)據(jù)行的版本號(hào)),DT_ROLL_PT(刪除版本號(hào)),
插入:當(dāng)進(jìn)行數(shù)據(jù)插入時(shí),不管是手動(dòng)還是默認(rèn)開啟的事務(wù)都會(huì)分配到一個(gè)自增的事務(wù)ID,在commit的時(shí)候,把事務(wù)ID插入到DT_TRX_ID中
修改:會(huì)把當(dāng)前修改的事務(wù)ID,添加到數(shù)據(jù)的DT_ROLL_PT字段,同時(shí)生成一個(gè)新的版本,DT_TRX_ID也是這個(gè)事務(wù)的ID
-
查找:
1.查找數(shù)據(jù)行版本小于或等于當(dāng)前事務(wù)版本的數(shù)據(jù)行,這樣就能保證事務(wù)讀取的行要么是在事務(wù)開始前已經(jīng)存在,要么是當(dāng)前事務(wù)插入或修改過的
2.查找刪除版本要么是null,要么大于當(dāng)前事務(wù)版本號(hào)的記錄,確保查出的行記錄在事務(wù)開啟之前沒有被刪掉
兩個(gè)條件同時(shí)滿足
3.undo log是什么
是指事務(wù)開始之前,在操作任何數(shù)據(jù)之前,首先將需要操作的數(shù)據(jù)備份到一個(gè)地方(undo Log).
undo Log是為了實(shí)現(xiàn)事務(wù)原子性而出現(xiàn)的產(chǎn)物
undo Log在mysql InnoDB引擎中用來實(shí)現(xiàn)多版本并發(fā)控制
4.undo log 怎么實(shí)現(xiàn)事務(wù)的原子性
事務(wù)執(zhí)行過程中如果出現(xiàn)了錯(cuò)誤或者用戶執(zhí)行了rollback,mysql可以通過undo Log的備份將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)
5.undo Log 怎么實(shí)現(xiàn)多版本并發(fā)控制
事務(wù)未提交之前,Undo Log保存了未提交之前的版本數(shù)據(jù),Undo 中的數(shù)據(jù)可以作為數(shù)據(jù)舊版本快照,供其他并發(fā)事務(wù)進(jìn)行快照讀
6.當(dāng)前讀、快照讀
快照讀:sql讀取的數(shù)據(jù)來自快照就是快照讀,普通的select 就是快照讀,InnoDB快照讀,數(shù)據(jù)的讀取由cache(原本數(shù)據(jù))+undo(事務(wù)修改過的數(shù)據(jù))兩部分組成
當(dāng)前都:sql讀取的版本來自最新版本,通過鎖機(jī)制來保證讀取的數(shù)據(jù)無法通過其他事務(wù)來修改,update,insert,delete,select..lock in share mode,select ..for update 都是當(dāng)前讀
7.redo log
redo log指事務(wù)中操作的任何數(shù)據(jù),將最新的數(shù)據(jù)備份到一個(gè)地方(Redo Log)
redo log 的持久:不是隨著事務(wù)的提交而寫入的,在事務(wù)執(zhí)行過程中,便開始寫入,
redo log是為了實(shí)現(xiàn)事務(wù)的持久性而出現(xiàn)的產(chǎn)物:防止在發(fā)生故障的時(shí)間點(diǎn),尚有臟讀頁未寫進(jìn)磁盤,在重啟mysql的時(shí)候根據(jù)redo log進(jìn)行重做,從而達(dá)到事務(wù)中未入磁盤數(shù)據(jù)進(jìn)入持久化這一特性
一旦事務(wù)提交并且持久化落盤之后,此時(shí)redo log中對(duì)應(yīng)的事務(wù)數(shù)據(jù)記錄就失去了意義,所以redo log 是循環(huán)寫入的,可以理解成一個(gè)環(huán)形,頭部(寫入的的位置)快要追上尾部(持久化到磁盤的位置)時(shí),就全力來持久化磁盤,給寫入redo log 留下空間
8.redo buffer 通過什么策略持久化到redo log
一般有三種策略,Innodb_flush_log_at_trx_commit設(shè)置為0、1、2
設(shè)置為0,每秒從buffer->OS cache(操作系統(tǒng)緩存區(qū))-> dist(到磁盤) ,造成的問題是可能丟失一秒內(nèi)的事務(wù)
設(shè)置為1(默認(rèn)),每次提交事務(wù)都從buffer->OS cache(操作系統(tǒng)緩存區(qū))-> dist(到磁盤) ,最安全,但是性能最差
設(shè)置為2,從buffer->OS cache 是每次事務(wù)提交, 從 OS cache-> dist是每秒,這是最推薦的,因?yàn)槿绻鹠ysql異常,只可能丟失一個(gè)事務(wù),如果所在服務(wù)器崩潰,丟失一秒內(nèi)的事務(wù)
5.配置優(yōu)化
1.MySQL服務(wù)器參數(shù)類型
基于作用域,可以分為
全局參數(shù) 如:set global autocommit = on/off
會(huì)話參數(shù)(會(huì)話參數(shù)不單獨(dú)設(shè)置會(huì)采用全局參數(shù)),如:set session autocommit = on/off
注意:
全局參數(shù)的設(shè)置對(duì)于已存在的會(huì)話無法生效
會(huì)話參數(shù)的設(shè)置會(huì)隨著會(huì)話的銷毀而失效
全局類的統(tǒng)一配置建議配置在默認(rèn)配置文件中,否則重啟服務(wù)會(huì)導(dǎo)致配置失效
2.如何找到默認(rèn)配置文件
可以通過 mysql --help | grep -A 1 'Default options are read from the following files in the given order'來找到
有可能找多多個(gè)配置文件,后面加載的配置文件會(huì)把前面加載的配置文件覆蓋掉
3.全局配置文件哪些需要注意
最大連接數(shù)配置 :
max_connections,但是有時(shí)真實(shí)的最大連接數(shù)會(huì)比設(shè)置的要少,這是因?yàn)椋到y(tǒng)句柄數(shù)(打開文件的個(gè)數(shù))設(shè)置的小,可以通過ulimit -a來查看,通過/etc/security/limits.conf來設(shè)置,或者是因?yàn)椋琺ysql的句柄數(shù)配置的小 可以通過/usr/lib/systemd/system/mysqld.service來設(shè)置lower_case_table_names = 0表名區(qū)分大小寫-
內(nèi)存參數(shù)配置:
1.每一個(gè)connection內(nèi)存參數(shù)配置:
sort_buffer_size排序緩沖區(qū)大小,建議 256k-2M之間,join_buffer_size關(guān)聯(lián)查詢緩沖區(qū)大小 建議 256k-1M之間,如配置400個(gè)連接,4000*(0.256M+0.256M)= 2G2.
Innodb_buffer_pool_size(非常關(guān)鍵),默認(rèn)是 128M,Innodb_buffer_pool_size中有數(shù)據(jù)緩存、索引緩存、緩沖數(shù)據(jù)、內(nèi)部結(jié)構(gòu),大的緩沖池可以減少多次磁盤I/O訪問相同表數(shù)據(jù)以提高性能,參考計(jì)算公式:Innodb_buffer_pool_size = (總物理內(nèi)存-系統(tǒng)運(yùn)行所用-connection所用) 90%* 其他參數(shù)配置:見 https://www.cnblogs.com/wyy123/p/6092976.html
6.數(shù)據(jù)庫(kù)設(shè)計(jì)
1.三大范式
所有字段值都是不可分解的原子值 (每一個(gè)列只有一個(gè)單一的值,不可再拆分)
在一個(gè)數(shù)據(jù)庫(kù)表中,一個(gè)表中只能保存一種數(shù)據(jù),不可以把多種數(shù)據(jù)保存在同一張數(shù)據(jù)庫(kù)表中 (每一個(gè)表都不包含其他表已包含的非主鍵信息)
每一列數(shù)據(jù)都和主鍵直接相關(guān),而不能間接相關(guān) (每一行都有主鍵進(jìn)行區(qū)分)
但是不一定非要完全三大范式來做,因?yàn)?,如果完全滿足第一范式,那么造成表有太多的列,完全滿足第三范式,就造成過多的表關(guān)聯(lián)