基礎教材系列:數據庫原理及應用(索引為什么快,數據在磁盤上如何存儲)網課筆記


引子:
1、數據庫有三級模式。
2、物理獨立性:數據在磁盤上存儲。
3、邏輯獨立性:表的邏輯設計。
4、兩級映射,表的邏輯不會其物理存儲邏輯。
5、視圖層:dba給用戶展示的部分內容。
 
一  數據模型
1、層次數據模型,樹
2、網狀數據模型
3、 關系模型
  3.1 基本結構就是表。現實世界中的實體用表來表達,實體之間的聯系,也用“表”來表達。
  3.2 查詢的是表,查詢出來的還是表,因為它是這樣一個封閉的空間,所以可以用數學的方法,即關系代數中的集合論,來研究數據。
  3.3 sql語法,就是以關系演算為基礎的,它不需要推理過程,關系代數則用來推理數據如何查出來的過程。
  3.4 表里每一行,叫作元組,一個表中的所有元組,組成一個集合。
  3.5 sql是非過程化的。非過程化是指我告訴數據庫我要什么,數據庫給我查出來,而我不用關心它是怎么查出來的。過程化是要寫代碼,去執行,才能把數據查出來,層次模型和網狀模型就是過程化的查詢。
  3.6 軟連接,就是id,通過id能找到一條數據。而層次和網狀,在面對一對多,多對多等關聯關系時,存儲的是對方的物理地址,這叫硬連接。
  3.7 關系數據模型在70年代就取代了層次和網狀成為主流,但並不意味着人們就對它滿意。以上三種屬於傳統數據模型,他們也有很多缺點,比如關系數據模型語義不清,如果沒有文檔,一個新人是看不出來表與表之間的聯系的。
后來有人提出:
      3.7.1 er數據模型,結果沒發展起來,反而成了描述數據關系的er圖。像關系數據模型語義不清,用er圖來表示就很清晰了,省寫文檔。er圖是需求分析和數據庫設計階段用的。
     3.7.2 面向對象數據模型,與關系相比,它突破了一范式限制。也沒發展起來。
 
二  SQL
 
1、數據模型是DMS的核心
2、DBMS提供的用戶接口:查詢語言,訪問工具(GUI),api(給代碼調的,如jdbc),類庫(如給java、c++編寫的) 
3、sql,原指結構化查詢語言,1986年改叫標准查詢語言,還是簡稱sql,它有四個子集。
sql中的關鍵字:Base table, View, Data type supported, NULL, UNIQUE, DEFAULT, PRIMARY KEY, FOREIGN KEY, CHECK(Integration Constraint)
 
四 sql語句講解
 
1、from后跟幾張表,底層(DBMS)就會做幾張表的笛卡爾乘積(假如a表三個字段,b表四個字段,乘積出來就是七個字段,還有所有的數據)。然后根據where條件排除不要的數據。笛卡爾乘積會出現很多無用數據,效率低,后面會講如何優化。
 
不同的數據庫產品要注意這些別名、模糊查詢等小方法的區別。
select s.age, age1 = s.age-5,2*s.age as age2 from sailors s where s.sname like 'b_%b';
 
2、查詢時,善用集合思維,比如union取並集,intersect取交集等。
3、in與exists,子小主大用in,相反用exists, 區別詳解點我
4、group by 和 having,先用where條件篩選數據,再用group by 的條件分組,然后再用having把每組的數據再篩選。
如果select后還有聚合函數,那它將在group by分組后,在每個組里執行聚合函數,比如count,min,都是計算本分組的總數,最小值。
語法規定,select、having后面的內容,必須是group by內容的子集(當然聚合函數除外)。
SELECT S.rating, MIN(S.age)
FROM Sailors S
WHERE S.age > 18
GROUP BY S.rating
HAVING 1 < ( SELECT COUNT(*) FROM Sailors S2 WHERE S2.rating = S.rating)
    
其他語法:
CAST expression, CASE expression, Sub-query, Outer Join, Recursion
 
5、cast,用來賦值。
SELECT name ,rank,
  CAST (NULL AS Varchar(20)) AS subject,
  CAST (NULL AS Integer) AS enrollment
FROM teacher-only
 
6、case,case某個字段,查出值;或直接case when...,如:
SELECT sum(CASE
  WHEN type = 'chain saw' THEN accidents
  ELSE 0e0
      END) / sum(accidents)
FROM Machines;
 
 
7、子查詢可以是一個范圍,亦可以是一個值(它可以出現在select后面)
8、一段子查詢需要用多次,可以將它定義為公共表表達式(就是下面要說的臨時視圖),相當於一個臨時視圖。用with定義,寫在前面
WITH payroll (deptno , totalpay) AS 
  (SELECT deptno ,sum(salary)+ sum(bonus)
  FROM emp 
  GROUP BY deptno)
SELECT deptno FROM payroll WHERE totalpay = 
  (SELECT MAX(totalpay) FROM  payroll);
 
9、遞歸查詢。emm...用到再去詳細了解吧,但老師解決問題的思路很號,把復雜查詢,簡化成一個對臨時表的查詢篩選!
sql的重點還是查詢呀
10、視圖
分為普通視圖、臨時視圖(如with)。
 
真正存儲在磁盤上的表,叫做基表,而視圖所查出的表叫虛表,虛表數據不落磁盤,磁盤上只存儲視圖的定義(新建個數據庫時,視圖都被存在其自帶的系統表里),用的時候臨時查出來數據,將其看作一個表。
視圖可以用作權限控制,比如某些數據不想給人看,就可以創建個視圖,然后讓這人看這個視圖里的數據就好了。
需要做視圖更新時,要看它適不適合做。
General view的定義存在數據庫里,temporary view連定義也是臨時的,不存數據庫
 
11、數據庫如何與語言配合
    1)嵌入式sql:比如sql寫到c語言代碼里,通過預編譯將sql與代碼分開,然后調用c的函數庫執行
    2)api:對sql的函數調用,定義一套規則,mysql、oracle等不同廠家都去實現這套規則。如odbc、jdbc
    3)直接用編程語言的類庫去調。
數據庫的原理,一直沒有變,而嵌入sql,api和類庫調用只不過是為了讓人用起來更方便而已,但本質卻沒有變化。
 
查詢時,如何把查詢出的集合,作為一個新的變量使用呢?用游標。
12、游標
游標用時,就open它,一open,就會執行游標定義的sql,然后返回一個集合,就可以把這個集合,當成是一個文件,然后使用這個游標的名字,就好像在使用這個文件一樣,讀文件會用指針嘛,與此類似,使用fetch,拿到當前元組的數據,into到你設置的變量里,然后循環,就像放下一個指針的數據,再fetch into,最后數據讀完了,會有標志位提示當前的程序設計語言,讓他別循環了,然后關閉游標,這一切資源也就被釋放了。示例如下:
 
13、存儲過程:
就是一組經常被調用的、要完成某個邏輯的sql,省得每次重復寫它了。語句會被dbms編譯優化
 
 
三  數據庫管理系統(DBMS)(本文重點)
 
1、DMBS實現原理總體架構
            1.1一個應用和數據庫連接,DBMS的deamon會監聽端口,看誰連過來,有人連,就給他建立個線程,讓他和dbms通信,如果對方是遠程鏈接,就用socket通信,如果是本地,就用pipe通信,通信只接收sql,返回結果。連接結束了,應用那邊要close這個鏈接,然后這個線程就會被操作系統回收。(這讓我想到了,當年jdbc為啥非要session.close,集采的數據庫會出現連接滿了的情況,就是因為用plsql連的數據庫,然后線程沒關,線程池就滿了。)
                deamon只管接人,開線程,別的不管。
            1.2 數據庫底層的文件存儲方式
                1.2.1存儲的物理方式:硬盤是塊狀存儲,基本單位是1kb/塊,磁頭每次取數據,至少掃描一個塊兒大小。
假如表里一個元組,數據加起來一共100b,則一個塊里可以放10個元組(通俗講就是10條數據),DBMS在查詢時,就把每一塊的數據讀出來,看看里面有沒有自己要找的。
                1.2.2存儲的邏輯方式:常見的關系型數據,其最基本常見的存儲方式:
                        1.2.2.1    堆——隨着文件的插入,不停地往其尾巴上堆。它的訪問路徑就是順序掃描,掃完了才能查到數據。
                        1.2.2.2    hash——其文件的hash值,就是其存儲地址。
                        1.2.2.3    索引+堆:對堆文件的某一列,建立b+樹索引(非葉節點僅有索引作用,信息存在葉節點, B樹與B+樹對比
                        1.2.2.4    其他:動態hash(普通索引可能分配的空間過小、或者過大,不如動態更高效)、raw disk(自己申請硬盤空間,自己決定物理存儲方式,而跳過操作系統的存儲方式,這樣的目的是:減少磁頭尋道時來回移動(這是查詢慢的關鍵),從而提升查詢速度。這叫簇集存儲,因為它是按照一定順序存的,所以可以將其看作是個索引)
索引技術分類:
B+ Tree,Clustering index, Inverted file, Dynamic hashing, Grid structure file and partitioned hash function , Bitmap index (used in data warehourse), Others。
 總之,關系型數據庫用的最多的,就是B+樹索引、簇集索引。
 
2、查詢sql在DBMS中如何優化
關系型數據庫剛提出時,很多人反對,因為關聯查詢需要做多個表的笛卡爾乘積,然后逐一筆記,效率太低。但后來關系型數據庫成為主流,就是因為它通過查詢優化,解決了這個瓶頸。
        2.1代數優化:將sql先改寫一下,等價、但運算次數少(高效),成為更優的形式。
                比如dbms進行語法分析,生成查詢樹,然后可以根據查詢條件先篩選數據,這樣可能要關聯查詢的數據就少了。
        2.2操作優化:sql進行具體操作時的優化方法。
                 一元操作簡單,難的是二元操作,就像左連接、右連接這種兩表關聯查詢。           
    關系型數據庫最影響效率的就是聯結運算。因為表設計要滿足一張表只做一件事,這樣就導致查詢時需要關聯查詢,而關聯查詢需要兩個表的笛卡爾乘積,所以很慢。
            關系型數據庫常用的聯結查詢優化算法如下:
            2.2.1內循環:倆表都取一個塊兒,放到內存里,然后一個一個比較。比完這個塊繼續比下一個塊。 
            2.2.2聯結查詢時,使用索引:比如兩個表關聯查詢,一個表先把一部分物理塊兒,讀入內存,然后做投影,看其連接屬性(就是外鍵,即類似join語句里最后的where a.bid=b.id)有多少不同的值,然后用這幾個不同的值,去查另一個表的b+樹索引(不加索引的話就把表里的每個元組都查一遍,又導致尋道時間增加,而索引就不用),然后匹配索引值,根據索引值,直接拿到那條數據的地址。
            所以,索引就是避免了內循環對表的掃描。
            如果,剛才說的另一個表的b+樹索引的列,重復值數量占總數20%以上,就不適合用索引了,因為你最后匹配索引值,拿到數據地址,因為有重復所以會拿到多個數據,多個數據可能會涉及到硬盤的很多物理塊兒,這樣取這些數據的尋道時間還是要消耗很多,那么用索引的效果就不明顯了。
            所以,用索引也不是永遠有效。 (索引這一講在視頻數據庫管理系統第8課)
            2.2.3 hash:在需求分析時,如果兩表不用更新,將兩表的聯結屬性,hash一下,然后放到hash文件里,這樣查詢直接查這個hash文件里的值即可,就不用像上面那樣做那么多操作了。
 
            dump,數據庫備份數據。可以備份全部,也可以備份每次更新的那部分;現在企業級的做法是備份+日志。這樣可以把來不及備份的內容,通過日志,進行補操作,來恢復到離故障點最近的時間。
 
            正如操作系統運行的基本單位是進程,數據庫運行的基本單位是事務,事務有四個特點:acid,原子一致隔離持久;如果沒用事務,那么dbms會把每條sql當作一個事務運行。
            dbms會為每一個事務賦予一個TID,正在操作的事務存到active list表,操作完成的事務放在commit list表。如果遇到斷電,有三種情況:
The recovery after failure in this situation ,check two lists for every TID while restarting after failure:
Commit list  Active list  
  delete TID from active list
redo, delete TID from active list
  nothing to do
 
第一種因為事務還沒對數據庫操作,所以刪了tid就好。
第二種需要檢查並對比active list表和commit list表,兩表都有數據,就說明事務正要提交就斷電了,這時把active list里的事務,操作一下,讓它執行完並提交事務,然后將其從active list里刪除。(就算此時再停電也沒事,繼續搬)
第三種,說明事務已經提交了,不用管。
3、DBMS的事務管理,並發控制
    3.1數據庫里的並發事務沖突,分為兩大類:寫寫沖突(如丟失更新)、讀寫沖突(如不可重復度,還有臟讀屬於寫讀沖突)
    3.2、並發控制,控制的就是:運行結果可串行化(n個事務同時給數據庫,會有n!個順序執行結果,dbms的執行結果只要是n!個結果之一就行)。
            要保證結果串行化,就要加鎖,其原則就是:每個對象上有個鎖,並行的事務按照它們搶到鎖的順序,去執行串行化。
 
四  安全與約束
 
五  數據庫設計
    1NF:表中每個屬性都是原子的。
    2NF:在1NF基礎上,消除屬性對主鍵的部分函數依賴得到。
    3NF:在2NF基礎上,消除屬性對主鍵的傳遞依賴得到。
    精華就四個字:一事一地——一張表只干一件事。 
 
    軟件工程流程是:需求分析(看對業務理解對不對)——概要設計(畫業務實體的er圖,不管用什么DBMS)——邏輯設計(根據選的dbms類型,設計具體的表和屬性的定義,這一步視圖等也要確定,也不用再和用戶討論)
 
    1、實際中的應用:
            傳統的企業,各部分可能交流不暢,但在信息化管理時,不能再按照傳統企業的模式去設計。
比如,多個部門都有自己的員工,不可能以部門為中心,為每個部門設計個員工表,這樣表直接就會重現很多重復,而且一個人如果經歷過很多部門,它的數據記錄起來就會很麻煩。
所以,為企業的數據庫設計,除了遵從三大范式,還應該秉承以數據為中心的原則,一個人,就是一個數據,而不是一個部門。
現實中的每一個概念、每一個基本元素,必須來源唯一,責任唯一。看每個屬性是否與其他有沖突、混淆、異名同意的現象,真正做到每個屬性都是唯一的。
            還有個例子:員工表有些隱私信息,不能讓人看,於是單獨建了個表放這些信息。這樣做是不對的,應該建立視圖。
    總之,要通過需求分析理清——最原子的概念是什么?
    僅僅在結構上達到3大范式是不夠的。“一事一地”包括每項信息的唯一,要提取出問題的本質,識別出本質上同一概念的信息項。對於表達類似信息,模式相似只是取值不同的表,應盡量合並。考慮到效率、用途等因素,該分開的表還應該分開。結合DBMS內部實現技術,合理設計索引和文件結構,為查詢優化准備好存取路徑。在結構規范化、減少數據冗余和提供數據庫訪問性能之間仔細權衡,適當折中。
 
六  分布式數據庫
數據庫分割方法:根據查詢需要,可以將一個表,根據業務不同, 分割成不同的裂片,分布在不同的節點上。
 
七  數據庫其他領域
數據倉庫、數據挖掘:將積累下來的海量數據,進行挖掘,分析,為我們經營決策提供一些支持。
數據倉庫是將數據,按照決策分析需求,重新收集起來。它主要做復雜的查詢,也不需要數據是最新的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM