1. 程式人生 > >【資料庫】基礎知識要點

【資料庫】基礎知識要點

不論做機器學習,還是後臺開發,都需要了解資料庫的基本知識,這一篇blog主要是總結資料庫的一些基本概念。並不是為了講解,重點就是總結梳理。

資料庫主要是面向業務邏輯的,所以為了滿足前端業務對資料的需求,資料庫管理系統負責完成資料的定義、阻止、儲存、管理、操作、事務管理等功能。所以資料庫的學習內容裡,最核心的就是資料庫管理系統DBMS

一、資料庫的資料組織模型與模式層級劃分

資料庫對資料的組織主要分為層次模型、網狀模型、關係模型。
層次模型從資料結構的角度看就是樹狀結構,而網狀模型則是圖結構。當然,網狀模型更好地描述世界中事物之間的關係,而層次模型受限,但是容易導致資料結構的爆炸式增長。現在最常用的資料模型就是關係模型,即關係資料庫。

不論是哪一種資料結構組織成的資料庫,都可以分為邏輯結構和具體數值兩部分,具體儲存的資料數值必須按照這種邏輯結構來儲存,否則就會報錯。而針對某一個應用將邏輯結構確定下來,就成了一個具體的模式。模式就是資料庫中全體資料的邏輯結構和特徵的描述。

一般來說,流行的資料庫都提供了三級模式結構,即外模式、模式、內模式

  • 模式:是資料庫中全體資料的中間層,描述了資料的邏輯結構和特徵,是所有使用者的公共資料檢視。DDL語言可用來描述模式中的邏輯,針對一個DB,只存在一個模式
  • 外模式:是指資料庫對外界的應用程式、外界使用者呈現出來的一種檢視,它並不代表真正的邏輯結構,僅僅是一種映像。如果應用程式不同、使用者不同,則外模式就不同。
  • 內模式:又稱儲存模式,一個數據庫只有一個儲存模式。由於DBMS管理員在建立資料庫模式的時候,並不關心底層細節,只關心邏輯通順與否,所以這裡需要構建一個內模式用來將邏輯模式和物理儲存方式對應起來。當然,內模式也不僅僅是邏輯和儲存的對應,還包括索引、壓縮、加密等等。這裡就有資料結構裡提到的資料庫的索引方法,B+樹,用來加速資料庫查詢速度,當然也有hash索引,這種速度更快,但是對記憶體的消耗還是很大的。
二、關係資料庫

關係資料庫的資料組織形式就是關係模型,從實際應用角度,舉一個學生選課資料庫比較好理解,但是從理論角度來講,關係資料模型主要包括(相同資料型別的值的集合),笛卡爾積(域的集合運算,每一個分量都是一個元組),關係

(笛卡爾積的子集叫做在域上的關係,具體到例項裡面,一個關係就可以抽出來作為一張資料庫的表)。

在一個關係(或一張表)裡,主碼、候選碼、主屬性、非主屬性(非碼屬性)等等概念就不贅述了,有時候碼又稱為鍵。全碼意味著表裡的所有屬性都是候選碼,即缺一不可,缺一則無法定義其中一個元組。需要注意的是,一張表中,候選碼才是決定元組唯一的因素,而主碼只是候選碼其中的一個,主碼是從經驗角度對候選碼的簡化。在實際應用過程中,我們可以說整個表中的屬性組合就是一個超碼,因為每一個元組自身都可以描述自己的唯一性,但是存在一個最小超碼,這個最小超碼就是候選碼,候選碼可以有很多個,但是主碼只有一個,那就是最方便資料庫表操作的一個或一組屬性。

關係資料庫的基本操作主要有關係演算(查詢、插入、刪除);查詢操作又包括關係代數(選擇、投影、連線、除、並、差、交、笛卡爾積)

三、關係資料庫的完整性

關係資料庫的完整性是指資料庫中的資料一些語義,只有保證這些語義正確,才能保證對資料庫的操作不會出現錯誤。

  • 實體完整性
    表中的每一個元祖都必須主屬性完整,也就是候選碼中的各個屬性必須存在。如果違反了實體完整性,就會拒絕插入或修改,比如插入的主碼和表中一個元組一樣,或者插入的元組的主碼其中一項為空。
  • 參照完整性:如果一個屬性並非表中(或關係中)的碼,但是它又和其他表中的主碼,則稱該屬性為外碼。外碼可以有兩種取值,一種是空值,另一種是對應的其它表中的主碼的值。
    如果違反了參照完整性,有若干種解決方案:一是拒絕執行這個操作;二是級聯修改,即外碼與對應的表中的主碼不一致時,就級聯刪除或者級聯修改,強制它們一致;三就是設定該處為空,這樣也可以保證參照完整。具體選擇哪種方法視情況而定。
  • 使用者定義完整性:即具體問題具體分析的完整性定義。SQL提供了CHECK關鍵字來幫助檢查使用者定義完整性,即對域的取值設定範圍規定。

如果對於一個表、或一個模式的完整性條件非常多,每次建立SQL語句都有很多的使用者定義完整性需要操作,那麼可以採用CONSTRAINT語句將CHECK和SQL語句獨立出來,方便每次的修改。

四、SQL

關係資料庫裡常用的語言就是SQL了,這也是資料庫裡的重點內容,相當的篇幅都在講SQL如何使用,SQL的特性等等。SQL集DDL(資料定義語言,主要是定義資料模式)、DML(資料操縱語言,包括查詢、刪除、插入等等)、DCL(資料控制語言,資料加密、完整性檢驗等等)於一體的,高度面向非過程的,而其他的關係代數和演算語言就可以忽略不計了。隨後另寫一篇blog總結一下SQL的語法和動詞,使用SQL的DBMS同樣支援關係資料庫的三種模式層級關係,模式就是管理員定義的資料邏輯模式結構,外模式稱為檢視,內模式就是在硬碟上儲存的檔案。很多DBMS比如MySQL都支援SQL語言,Oracle也支援,但是其間多少有一些細微的差別,但是這並不影響我們的使用。

我們在建立資料庫的時候,首先要定義一個模式,然後再在這個框架上定義表,模式和表的關係是一對多,如果沒有的話,DBMS會預設為我們建立一個模式,儘管我們沒有手動輸入模式,但是預設的模式名就是使用者名稱。

在資料庫的各種操作中,經常會碰到兩個引數 CASCADE 和 RESTRICTED,這兩個含義分別是指,對於操作的資料,與其關聯的資料是否要一起刪除,還是保留其他的關聯資料

檢視:外模式的一種實現形式。

它可以在模式基礎上向用戶提供更加豐富的操作更加豐富的看待資料庫的角度,也能將應用程式和資料庫的邏輯模式在一定程度上獨立出來,而且由於應用程式只能看到檢視,不能看到真正的邏輯模式,也提供了一定的資料安全性

儘管SQL高度非過程,但是仍然有一些具有過程性的語句,比如觸發器 TRIGGER,它是指在資料庫的操作中,一旦滿足了某些條件,即可觸發觸發器中的程式碼進行執行。

五、資料庫的安全性

1、 在進入資料庫時有使用者名稱和密碼登入,這個是使用者身份鑑定
2、 定義使用者許可權,其中一種是滿足電腦保安性等級C2的自助存取控制DAC:它是指不同的使用者對資料庫中的物件有不同的許可權,且同一使用者對不同的資料庫物件有不同的許可權,許可權分為檢視、更改和刪除等等。另一種滿足更高的安全等級B1,即對整個資料庫中的物件都進行密級劃分,只有滿足一定級別許可權的使用者才能訪問這些物件,否則不可以
使用者許可權的定義裡最典型的就是應用程式可以訪問的檢視,以及DBMS管理員可以訪問的模式。也就是說,外界使用者只能檢視外模式,只有管理員才可以訪問修改邏輯模式。
在SQL語言中,集成了DCL,所以安排了GRANT和REVOKE兩個動詞語句來實現對資料庫物件的授權和撤回。
3、 審計,這是一種監測手段,類似於攝像頭,DBMS提供監視操作,將所有的使用者和應用程式對資料庫的修改、檢視等資訊全部記錄在審計log中,這樣就可以對審計日誌進行分析,找出哪些非法使用者在何時操作了哪些資料。SQL裡提供了AUDIT動詞法語。
4、 再有一個方法就是資料加密,加密技術應用廣泛,尤其是在通訊中,使用了對稱非對稱的加密演算法,一般對於機密性非常高的資料,以及要在網路上傳輸的資料才會使用加密技術,因為加密的代價比較大,時間和空間的壓力都比較大。

六、關係資料庫的理論

單看理論是比較抽象的,一旦結合例子就顯得清晰多了。
關係模型可以用五元組來表示:關係名、一組屬性、屬性對應的域、屬性到域的對映、屬性上的一組資料依賴。前四個都比較好理解,資料依賴是指屬性之間的約束關係,主要包括函式依賴和多值依賴。

  • 函式依賴是指其中的一些屬效能夠唯一確定其他屬性,比如一個學生的學號確定下來之後,其姓名、學分等等都確定下來了。將函式依賴這一概念推廣到關係資料庫中的碼,候選碼即決定項,非候選碼即依賴項。若候選碼多於一個,則選擇一個是主碼,也就是說,關係資料庫的模式都滿足關係模型。
  • 多值依賴是指在一張表中,其中的某一些屬性受到其他若干屬性的影響進而產生依賴,這樣非常容易造成資料冗餘,難以處理。

正規化理論屬於邏輯學的內容。

  • 第一正規化:一個關係(或一張表)滿足了每一個分量都必須是不可分的資料項,也就是說表中不能含有表,就可以稱該關係資料庫滿足了第一正規化。
  • 第二正規化:在第一正規化的基礎上,每一個非主屬性完全依賴於碼,即稱滿足了第二正規化,也就是說,表可以構成一個整體了,資料的屬性相互之間有關聯。
  • 第三正規化:在第二正規化基礎上,資料表中如果不存在碼傳遞決定非主屬性,則稱該關係模型滿足第三正規化。這一條有點抽象,解釋一下,其含義是主屬性都是直接決定非主屬性,不存在中間的傳遞關係。
  • BCNF正規化:又稱擴充套件第三正規化,指每一個決定因素都包含碼在內
  • 第四正規化:第四正規化比BCNF更加嚴格,由於函式依賴是多值依賴的一種特殊情況,第四正規化的本質含義就是限制關係模型不允許多值依賴出現,只許有函式依賴。消除多值依賴需要SQL投影操作完成

七、資料庫程式設計

  1. 嵌入式SQL程式設計
    其主要方式就是採用高階語言進行流程控制,SQL語言進行資料庫操作。主流語言都提供了SQL語言程式設計介面,將要處理的SQL語句組織成字串傳遞給高階語言的介面,高階語言自己呼叫SQL來傳遞給DBMS進行處理。
    但是這其間有一個問題,就是嵌入式SQL語句和主語言之間的通訊方式:一種是DBMS向主語言編譯器、直譯器等等傳遞SQL語句執行的控制狀態資訊,這樣主語言即可根據這些資訊來決定如何進行下一步操作,這種方法就是SQL通訊區。另一種方法就是主語言向SQL語句提供引數,使用主變數來實現

    在嵌入式SQL中,為了彌合SQL面向集合,每次語句產生或多條記錄,而主變數則每次只能存放一條記錄這種矛盾,誕生了CURSOR這種東西,使用遊標可以方便地操作資料庫。遊標的本質就是使用者自己開設的一個數據緩衝區,將所有的SQL語句的執行結果存放在裡面,使用者利用該緩衝區將記錄逐個附在變數裡,告知主語言
    當然,如果查詢結果就是單條記錄,自然不需要遊標。

  2. 動態SQL程式設計
    其目的是使SQL查詢語句能夠根據執行狀態的不同而變化,因為在資料庫執行SQL語句的過程中,很可能主語言的需求就變化了,需要更改操作,這時候就需要更改SQL語句,執行新的操作,這個變數的更改就放在主變數裡,以適應隨時更改。
    除此之外,SQL語句本身提供了動態引數功能,即 ?符號,供開發者使用。

  3. 儲存過程
    在資料庫程式設計中,除了嵌入式SQL,還有PL/SQL,這是SQL語言的過程化擴充套件,讓其實現過程處理。PL/SQL語言中包含了賦值語句、控制結構、迴圈結構等等,和程式設計語言類似。PL/SQL語言編寫的程式的基本結構就是塊,塊與塊之間可以相互巢狀,每一個塊完成一個獨立的邏輯操作。這有點類似於高階程式語言中的函式概念。

    PL/SQL的塊主要有兩種型別,命名塊和匿名塊。匿名塊每次執行都需要編譯,也不可以儲存在資料庫中。而命名塊就可以在編譯之後儲存在資料庫中,被反覆呼叫,命名塊包括儲存過程和函式

    將若干PL/SQL語句構成的操作過程編譯和優化後存放在資料庫中,就被稱為儲存過程,每次執行的時候就呼叫一次。由於是預先編譯過的,所以執行起來不需要語法檢查,執行效率很高,所以經常在伺服器端使用。另外,儲存過程降低了客戶機和伺服器之間的通訊量。如果訪問伺服器,只要告知伺服器若干引數,讓伺服器呼叫儲存過程,這樣執行的效率就很高。在SQL語言中,採用 Procedure 關鍵詞進行儲存過程的建立、執行、刪除。同樣的,也有遊標可以用來對其操作。

  4. ODBC程式設計
    ODBC程式設計克服了各種不同型別的DBMS的異構性,提供了一個統一的操作介面,方便了程式的移植。使用ODBC開發應用程式,資料庫的介面是ODBC api,ODBC程式的另一頭是各種異構的資料庫比如SQL Server、Oracle等等。我沒有使用過ODBC,但是我感覺分散式開發的系統、或者更新換代的系統才會用到ODBC吧。

八、查詢優化

查詢處理是資料庫的核心操作,主要分為查詢分析、查詢檢查、查詢優化、查詢執行幾個階段。
查詢分析:對語句進行詞法、語法分析
查詢檢查:是指對語句中的資料物件進行檢查,比如說要查詢的表存在與否,屬性是否存在,查詢條件是否符合要求。檢查通過後,就把SQL語句轉換為等價的關係代數表示式(一般都是查詢樹、語法分析樹),DBMS會處理這個關係代數表示式。
查詢優化:即代數優化(優化關係代數表示式,即等價變換)和物理優化(基於存取路徑的優化)。

在資料庫優化中,主要是指選擇SELECT的優化 和連線優化

  • 資料庫選擇SELECT方法主要有以下幾種:
    1、全表掃描查詢:耗時,簡單粗暴。當然如果數量比較小還是比較有效的。
    2、索引、雜湊查詢:建立在B+數和雜湊表基礎上,時間複雜度大大降低,資料量越大越有效。但是索引並不是一定就能夠優化,在資料量比較小的時候,構建一顆索引樹的時間和空間代價也是比較大的,尤其是當資料庫更新頻繁的時候,索引樹需要經過旋轉、增添刪改等平衡化操作,而且如果樹儲存在外存上,讀取外存的時間和空間都是很大的開銷,雜湊更是如此。所以,在資料量超級龐大的情況下,再考慮建樹,當然了,這些問題DBMS都已經做過優化了。
  • 連線操作的方法,也就是將兩個以上的表連線在一起:
    1、 巢狀迴圈:簡單粗暴耗時。
    2、 排序-合併方法:依然是採用有序的表來進行表的連線,效率也是大大增加。
九、事務

事務:指使用者定義的一個數據庫操作,操作可能只包含一條SQL語句,也可能包含多條,比如,一個儲存過程就是一個事務,因為它已經編譯過了,不可再細分。事務的特性就包含原子性,即一個事務要麼都做,要麼都不做。另外、事務還要確保一致性,即事務處理前後的結果一定保證資料庫的狀態滿足事務處理的預期要求。事務必須確保隔離性,即事務的執行不能被其他事務干擾造成無法處理。事物的持續性即事務處理完成後,不會根據某種原因造成資料的改變或者丟失。

資料庫中的事務有點類似於作業系統中的程序和執行緒,當然資料庫的事務處理比程序和執行緒的處理略簡單一些,畢竟處理的僅僅是資料庫中的資料,而程序和執行緒涉及到的上下文很複雜。且事務的操作和併發控制緊緊聯絡在一起。

十、資料庫故障恢復

系統故障(DBMS執行的OS出現故障)、物理故障(磁碟掉磁)、病毒木馬(惡意篡改資料)是非事務故障,也就是說,單個DBMS自己無法解決的,DBMS可以克服的、機制最複雜的就是事務故障。

故障解決辦法有:

  1. 資料轉儲:即備份。靜態轉儲即轉儲其間不允許別的事務插手進來,比如網站團隊半夜維護網站;而動態轉儲允許轉儲過程中事務進來操作,此時就需要建立事務日誌log,記錄到底哪些資料動過了。另外,如果資料量太大,還需要增量轉儲,也就是隻轉儲改變的那一部分。轉儲技術不僅僅是克服故障的好辦法,同樣也是實現分散式的手段,分散式不僅僅可以克服故障,還能在存取效率上有很大的提升。現在已經可以實現DBMS自動把剛剛接收到的資料修改記錄立即傳送到資料轉儲的映象上的功能,即資料庫映象。
  2. 登記日誌檔案:這是資料庫故障恢復的核心,比如說磁碟掉磁了,登記日誌檔案都沒了,那就沒什麼好說的了,損失已經形成,時光不能倒流。具有檢查點的恢復技術其根本也是登記日誌檔案,只不過需要在檢查點附近討論到底哪些事務需要恢復,哪些事務不需要。
十一、事務併發

資料庫中建立了封鎖技術,和OS中的執行緒鎖類似,確保事務的一致性。
排他鎖:寫鎖,在增刪資料庫資料的時候不允許其它事務進來。
共享鎖:讀鎖,如果一個事務在讀取資料,那麼其它事務也可以進來讀資料,但是不能寫資料。

儘管有了鎖技術,但是還是會出現各種各樣的錯誤和問題,比如鎖,解決活鎖的方法是設定排隊佇列。而死鎖則可以採用預防、診斷、檢測等方法來處理,和OS處理死鎖的方法一樣。
同樣地,加鎖技術還會出現驚群現象,這個也是靠排隊佇列來解決。

在處理併發的過程中,為確保事務的一致性和隔離性,還需要採用可序列化排程保證資料的正確性。基於此需求,誕生了兩段鎖協議在事務讀寫之前,首先要申請鎖;在事務處理完成釋放封鎖之後,不允許再申請鎖。這是一個很強的條件,充分條件。

為了提高事務處理效率,需要進行多粒度封鎖,其含義就是把所有的資料庫的物件分為不同的粒度,庫級別最高,模式次之,表再次之,最後是一個個的元組。如果一個事務想要申請鎖,那麼就需要從多粒度樹的頭結點開始詢問,資料庫有沒有被加鎖?表有沒有被加鎖?如果都沒有被加鎖,則可以對自己想要操作的資料加鎖。意向鎖則是對多粒度加鎖協議的一種改進,避免訪問過多的物件,提高加鎖效率

上述技術DBMS都已經廣泛實現,也就是說,我們如果非必須只需要使用,而不需要知道其內涵到底是什麼。

現階段DBMS對應用程式的並行支援最高效的形式就是構建DBMS程序池,這樣可以提高應用程式和DBMS之間的協調性

十二、面向物件的資料庫技術

SQL支援面向物件技術,現在的DBMS都提供面向物件功能。也就是說,在資料角度上看,面向物件的RDBMS提供了LOB、MOB、BOOLEAN、ARRAY、DISTINCT等資料型別。也就是說,屬性的型別可以自定義了,也可以完成繼承,參照也有獨立的型別,即引用型別。講真這些東西我都沒有用過,等到用的時候再接觸吧。

十三、XML資料庫

SQL支援XML,我記得在做文字處理的時候需要將文字轉化成結構化的資料,看來這就是了,XML比SQL更加靈活,就是一個層級模型。

十四、資料倉庫

這兩年大資料這麼火,等隨後有時間再學習一下資料倉庫吧。這裡只是列一下基本的概念。
資料倉庫的目的並非面向業務,資料庫才是。所以資料庫更追求對資料處理的實時性、便捷性、操作細碎、雜亂、更新速度快。而資料倉庫則是面向分析的,目的不在於處理應用程式前端接收的業務,而是為了分析資料。所以資料不進行更新操作,資料量也較資料庫大很多,一個事務採集的資料量非常大,主要目的是資料探勘,供管理分析決策。

還有兩塊內容我空下來了。DBMS的系統組成,以及分散式資料庫。隨後再看再補吧。