【python web開發知識點整理4】- 數據庫基礎

【python web開發知識點整理1】- Python基礎
【python web開發知識點整理2】- Python Web基礎
【python web開發知識點整理3】- 容器基礎
【python web開發知識點整理4】- 數據庫基礎
【python web開發知識點整理5】- Linux基礎
【python web開發知識點整理6】- 設計模式

4. 數據庫基礎

4.1. 數據庫的優化

  1. 優化索引、SQL 語句、分析慢查詢;
  2. 設計表的時候嚴格根據數據庫的設計範式來設計數據庫;
  3. 使用緩存,把經常訪問到的數據而且不需要經常變化的數據放在緩存中,能節約磁盤IO;
  4. 優化硬件;採用SSD,使用磁盤隊列技術(RAID0,RAID1,RDID5)等;
  5. 採用MySQL 內部自帶的表分區技術,把數據分層不同的文件,能夠提高磁盤的讀取效率;
  6. 垂直分表;把一些不經常讀的數據放在一張表裏,節約磁盤I/O;
  7. 主從分離讀寫;採用主從複製把數據庫的讀操作和寫入操作分離開來;
  8. 分庫分表分機器(數據量特別大),主要的的原理就是數據路由;
  9. 選擇合適的表引擎,參數上的優化;
  10. 進行架構級別的緩存,靜態化和分佈式;
  11. 不採用全文索引;
  12. 採用更快的存儲方式,例如 NoSQL存儲經常訪問的數據

4.2. 什麼是索引?

數據庫索引,是數據庫管理系統中一個排序的數據結構,索引的實現通常使用B樹及其變種B+樹。
在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

4.4. 索引的優缺點?

4.4.1. 創建索引可以大大提高系統的性能(優點):

  1. 通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
  2. 可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。
  3. 可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
  4. 在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。
  5. 通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

4.4.2. 增加索引也有許多不利的方面(缺點):

  1. 創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加。
  2. 索引需要佔物理空間,除了數據表佔數據空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。
  3. 當對錶中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。

4.5. 哪些列適合建立索引、哪些不適合建索引?

索引是建立在數據庫表中的某些列的上面。在創建索引的時候,應該考慮在哪些列上可以創建索引,在哪些列上不能創建索引。

4.5.1. 一般來說,應該在這些列上創建索引:

  1. 在經常需要搜索的列上,可以加快搜索的速度;
  2. 在作爲主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;
  3. 在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;
  4. 在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,其指定的範圍是連續的;
  5. 在經常需要排序的列上創建索引,因爲索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;
  6. 在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。

4.5.2. 對於有些列不應該創建索引:

  1. 對於那些在查詢中很少使用或者參考的列不應該創建索引。
    這是因爲,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。
  2. 對於那些只有很少數據值的列也不應該增加索引。
    這是因爲,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,並不能明顯加快檢索速度。
  3. 對於那些定義爲text, image和bit數據類型的列不應該增加索引。
    這是因爲,這些列的數據量要麼相當大,要麼取值很少。
  4. 當修改性能遠遠大於檢索性能時,不應該創建索引。
    這是因爲,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引。

4.7. MySQL B+Tree索引和Hash索引的區別?

Hash索引和B+樹索引的特點:
Hash索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位;
B+樹索引需要從根節點到枝節點,最後才能訪問到頁節點這樣多次的IO訪問;

4.7.1. 爲什麼不都用Hash索引而使用B+樹索引?

  • Hash索引僅僅能滿足"=",“IN"和”"查詢,不能使用範圍查詢,因爲經過相應的Hash算法處理之後的Hash值的大小關係,並不能保證和Hash運算前完全一樣; Hash索引無法被用來避免數據的排序操作,因爲Hash值的大小關係並不一定和Hash運算前的鍵值完全一樣;‘
  • Hash索引不能利用部分索引鍵查詢,對於組合索引,Hash索引在計算Hash值的時候是組合索引鍵合併後再一起計算Hash值,而不是單獨計算Hash值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash索引也無法被利用;
  • Hash索引在任何時候都不能避免表掃描,由於不同索引鍵存在相同Hash值,所以即使取滿足某個Hash鍵值的數據的記錄條數,也無法從Hash索引中直接完成查詢,還是要回表查詢數據;
  • Hash索引遇到大量Hash值相等的情況後性能並不一定就會比B+樹索引高。

4.7.2. 補充:

  1. MySQL中,只有HEAP/MEMORY引擎才顯示支持Hash索引。
  2. 常用的InnoDB引擎中默認使用的是B+樹索引,它會實時監控表上索引的使用情況,如果認爲建立哈希索引可以提高查詢效率,則自動在內存中的“自適應哈希索引緩衝區”建立哈希索引(在InnoDB中默認開啓自適應哈希索引),通過觀察搜索模式,MySQL會利用index key的前綴建立哈希索引,如果一個表幾乎大部分都在緩衝池中,那麼建立一個哈希索引能夠加快等值查詢。
  3. 如果是等值查詢,那麼哈希索引明顯有絕對優勢,因爲只需要經過一次算法即可找到相應的鍵值;當然了,這個前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然後再根據鏈表往後掃描,直到找到相應的數據;
  4. 如果是範圍查詢檢索,這時候哈希索引就毫無用武之地了,因爲原先是有序的鍵值,經過哈希算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索;
    同理,哈希索引沒辦法利用索引完成排序,以及like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢);
  5. 哈希索引也不支持多列聯合索引的最左匹配規則;
  6. B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重複鍵值情況下,哈希索引的效率也是極低的,因爲存在所謂的哈希碰撞問題。
  7. 在大多數場景下,都會有範圍查詢、排序、分組等查詢特徵,用B+樹索引就可以了。

4.8. B樹和B+樹的區別

B樹,每個節點都存儲key和data,所有節點組成這棵樹,並且葉子節點指針爲nul,葉子結點不包含任何關鍵字信息。
B+樹,所有的葉子結點中包含了全部關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大的順序鏈接,所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (而B 樹的非終節點也包含需要查找的有效信息)

4.9. 爲什麼說B+比B樹更適合實際應用中操作系統的文件索引和數據庫索引?

  1. B+的磁盤讀寫代價更低
    B+的內部結點並沒有指向關鍵字具體信息的指針。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。

  2. B+tree的查詢效率更加穩定
    由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

4.11.4. Hash 索引

  • Hash 索引簡單說就是對索引字段的離散化
  • 使進行查詢時可以通過離散化規則計算得到對應的位置,進行對應的查詢
  • 這種對於查詢指定條目的數據性能非常快
  • 但是無法完成常見的 範圍搜索查詢,排序等操作

4.10. 聚集索引和非聚集索引區別?

4.10.1. 聚合索引(clustered index):

聚集索引表記錄的排列順序和索引的排列順序一致,所以查詢效率快,只要找到第一個索引值記錄,其餘就連續性的記錄在物理也一樣連續存放。聚集索引對應的缺點就是修改慢,因爲爲了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁重新排序。
聚集索引類似於新華字典中用拼音去查找漢字,拼音檢索表於書記順序都是按照a~z排列的,就像相同的邏輯順序於物理順序一樣,當你需要查找a,ai兩個讀音的字,或是想一次尋找多個傻(sha)的同音字時,也許向後翻幾頁,或緊接着下一行就得到結果了。

4.10.2. 非聚合索引(nonclustered index):

非聚集索引指定了表中記錄的邏輯順序,但是記錄的物理和索引不一定一致,兩種索引都採用B+樹結構,非聚集索引的葉子層並不和實際數據頁相重疊,而採用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非聚集索引層次多,不會造成數據重排。
非聚集索引類似在新華字典上通過偏旁部首來查詢漢字,檢索表也許是按照橫、豎、撇來排列的,但是由於正文中是a~z的拼音順序,所以就類似於邏輯地址於物理地址的不對應。同時適用的情況就在於分組,大數目的不同值,頻繁更新的列中,這些情況即不適合聚集索引。

4.10.3. 根本區別:

聚集索引和非聚集索引的根本區別是表記錄的排列順序和與索引的排列順序是否一致。

4.12. 你常用的mysql引擎有哪些?各引擎間有什麼區別?

主要 MyISAM 與 InnoDB 兩個引擎,其主要區別如下:

  • MyISAM 適合於一些需要大量查詢的應用,但其對於有大量寫操作並不是很好。甚至你只是需要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都無法操作直到讀操作完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。
  • InnoDB 的趨勢會是一個非常複雜的存儲引擎,對於一些小的應用,它會比 MyISAM 還慢。他是它支持“行鎖”,於是在寫操作比較多的時候,會更優秀。並且,他還支持更多的高級應用,比如:事務。
  • InnoDB 支持事務,MyISAM不支持,這一點是非常之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪個出錯還可以回滾還原,而 MyISAM就不可以了;
  • MyISAM 適合查詢以及插入爲主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用;
  • InnoDB 支持外鍵,MyISAM 不支持;
  • MyISAM 是默認引擎,InnoDB 需要指定;
  • InnoDB 不支持 FULLTEXT 類型的索引;
  • InnoDB 中不保存表的行數,如 select count(*) from table 時,InnoDB;需要掃描一遍整個表來計算有多少行,但是 MyISAM只要簡單的讀出保存好的行數即可。注意的是,當 count(*)語句包含 where 條件時 MyISAM 也需要掃描整個表;
  • 對於自增長的字段,InnoDB 中必須包含只有該字段的索引,但是在 MyISAM表中可以和其他字段一起建立聯合索引;
  • 清空整個表時,InnoDB 是一行一行的刪除,效率非常慢。MyISAM 則會重建表;
  • InnoDB 支持行鎖(某些情況下還是鎖整表,如 update table set a=1 where user like '%lee%'

4.13. 數據庫中的事務是什麼?

數據庫事務(Database Transaction),是指作爲單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。如果所有操作完成,事務則提交,其修改將作用於所有其他數據庫進程。如果一個操作失敗,則事務將回滾,該事務所有操作的影響都將取消。ACID 四大特性,原子性、隔離性、一致性、持久性。

事務特性:

  1. 原子性:即不可分割性,事務要麼全部被執行,要麼就全部不被執行
  2. 一致性或可串性:事務的執行使得數據庫從一種正確狀態轉換成另一種正確狀態
  3. 隔離性:在事務正確提交之前,不允許把該事務對數據的任何改變提供給任何其他事務
  4. 持久性:事務正確提交後,其結果將永久保存在數據庫中,即使在事務提交後有了其他故障,事務的處理結果也會得到保存

4.13.1 事務的併發問題

  1. 髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據
  2. 不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。
  3. 幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

4.13.2 MySQL事務隔離級別

事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交(read-uncommitted)
不可重複讀(read-committed)
可重複讀(repeatable-read)
串行化(serializable)

4.14. 主鍵、外鍵、超鍵、候選鍵

  • 超鍵:在關係中能唯一標識元組的屬性集稱爲關係模式的超鍵。一個屬性可以爲作爲一個超鍵,多個屬性組合在一起也可以作爲一個超鍵。超鍵包含候選鍵和主鍵。
  • 候選鍵:是最小超鍵,即沒有冗餘元素的超鍵。
  • 主鍵:數據庫表中對儲存數據對象予以唯一和完整標識的數據列或屬性的組合。一個數據列只能有一個主鍵,且主鍵的取值不能缺失,即不能爲空值(Null)。
  • 外鍵:在一個表中存在的另一個表的主鍵稱此表的外鍵。

4.15. 爲什麼用自增列作爲主鍵?

如果我們定義了主鍵(PRIMARY KEY),那麼InnoDB會選擇主鍵作爲聚集索引、
如果沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的唯一索引作爲主鍵索引、
如果也沒有這樣的唯一索引,則InnoDB會選擇內置6字節長的ROWID作爲隱含的聚集索引(ROWID隨着行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。
數據記錄本身被存於主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點內(大小爲一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,因此每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,如果頁面達到裝載因子(InnoDB默認爲15/16),則開闢一個新的頁(節點)
如果表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁
如果使用非自增主鍵(如果身份證號或學號等),由於每次插入主鍵的值近似於隨機,因此每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不爲了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷,同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,後續不得不通過OPTIMIZE TABLE來重建表並優化填充頁面。

4.12. 觸發器的作用?

觸發器是一種特殊的存儲過程,主要是通過事件來觸發而被執行的。它可以強化約束,來維護數據的完整性和一致性,可以跟蹤數據庫內的操作從而不允許未經許可的更新和變化。可以聯級運算。如,某表上的觸發器上包含對另一個表的數據操作,而該操作又會導致該表觸發器被觸發。

4.13. 什麼是存儲過程?用什麼來調用?

存儲過程是一個預編譯的SQL語句,優點是允許模塊化的設計,就是說只需創建一次,以後在該程序中就可以調用多次。如果某次操作需要執行多次SQL,使用存儲過程比單純SQL語句執行要快。
調用:

  1. 可以用一個命令對象來調用存儲過程。
  2. 可以供外部程序調用,比如:java程序。

4.14. 存儲過程的優缺點?

優點:

  1. 存儲過程是預編譯過的,執行效率高。
  2. 存儲過程的代碼直接存放於數據庫中,通過存儲過程名直接調用,減少網絡通訊。
  3. 安全性高,執行存儲過程需要有一定權限的用戶。
  4. 存儲過程可以重複使用,可減少數據庫開發人員的工作量。

缺點:

  1. 移植性差

4.15. 視圖的優缺點

優點:

  1. 對數據庫的訪問,因爲視圖可以有選擇性的選取數據庫裏的一部分。
  2. 用戶通過簡單的查詢可以從複雜查詢中得到結果。
  3. 維護數據的獨立性,試圖可從多個表檢索數據。
  4. 對於相同的數據可產生不同的視圖。

缺點:

  1. 性能:查詢視圖時,必須把視圖的查詢轉化成對基本表的查詢,如果這個視圖是由一個複雜的多表查詢所定義,那麼,那麼就無法更改數據

4.16. drop、truncate、 delete區別

最基本:

  • drop直接刪掉表。
  • truncate刪除表中數據,再插入時自增長id又從1開始。
  • delete刪除表中數據,可以加where字句。
  1. DELETE語句執行刪除的過程是每次從表中刪除一行,並且同時將該行的刪除操作作爲事務記錄在日誌中保存以便進行進行回滾操作。TRUNCATE TABLE 則一次性地從表中刪除所有的數據並不把單獨的刪除操作記錄記入日誌保存,刪除行是不能恢復的。並且在刪除的過程中不會激活與表有關的刪除觸發器。執行速度快。
  2. 表和索引所佔空間。當表被TRUNCATE 後,這個表和索引所佔用的空間會恢復到初始大小,而DELETE操作不會減少表或索引所佔用的空間。drop語句將表所佔用的空間全釋放掉。
  3. 一般而言,drop > truncate > delete
  4. 應用範圍。TRUNCATE 只能對TABLE;DELETE可以是table和view
  5. TRUNCATE 和DELETE只刪除數據,而DROP則刪除整個表(結構和數據)。
  6. truncate與不帶where的delete :只刪除數據,而不刪除表的結構(定義)drop語句將刪除表的結構被依賴的約束(constrain),觸發器(trigger)索引(index);依賴於該表的存儲過程/函數將被保留,但其狀態會變爲:invalid。
  7. delete語句爲DML(data maintain Language),這個操作會被放到 rollback segment中,事務提交後才生效。如果有相應的 tigger,執行的時候將被觸發。
  8. truncate、drop是DLL(data define language),操作立即生效,原數據不放到 rollback segment中,不能回滾。
  9. 在沒有備份情況下,謹慎使用 drop 與 truncate。要刪除部分數據行採用delete且注意結合where來約束影響範圍。回滾段要足夠大。要刪除表用drop;若想保留表而將表中數據刪除,如果於事務無關,用truncate即可實現。如果和事務有關,或老師想觸發trigger,還是用delete。
  10. Truncate table 表名 速度快,而且效率高,因爲:?truncate table 在功能上與不帶 WHERE 子句的 DELETE 語句相同:二者均刪除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少。DELETE 語句每次刪除一行,並在事務日誌中爲所刪除的每行記錄一項。TRUNCATE TABLE 通過釋放存儲表數據所用的數據頁來刪除數據,並且只在事務日誌中記錄頁的釋放。
  11. TRUNCATE TABLE 刪除表中的所有行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置爲該列的種子。如果想保留標識計數值,請改用 DELETE。如果要刪除表定義及其數據,請使用 DROP TABLE 語句。
  12. 對於由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。由於 TRUNCATE TABLE 不記錄在日誌中,所以它不能激活觸發器。

4.17. 非關係型數據庫和關係型數據庫區別,優勢比較?

4.17.1. 非關係型數據庫的優勢:

性能:NOSQL是基於鍵值對的,可以想象成表中的主鍵和值的對應關係,而且不需要經過SQL層的解析,所以性能非常高。
可擴展性:同樣也是因爲基於鍵值對,數據之間沒有耦合性,所以非常容易水平擴展。

4.17.1. 關係型數據庫的優勢:

複雜查詢:可以用SQL語句方便的在一個表以及多個表之間做非常複雜的數據查詢。
事務支持:使得對於安全性能很高的數據訪問要求得以實現。
其他:

  1. 對於這兩類數據庫,對方的優勢就是自己的弱勢,反之亦然。
  2. NOSQL數據庫慢慢開始具備SQL數據庫的一些複雜查詢功能,比如MongoDB。
  3. 對於事務的支持也可以用一些系統級的原子操作來實現例如樂觀鎖之類的方法來曲線救國,比如Redis set nx。

4.18. MySQL慢查詢怎麼解決?

  1. slow_query_log 慢查詢開啓狀態。
  2. slow_query_log_file慢查詢日誌存放的位置(這個目錄需要MySQL的運行帳號的可寫權限,一般設置爲MySQL的數據存放目錄)。
  3. long_query_time 查詢超過多少秒才記錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章