數據庫知識面試總結

                                                        數據庫面試知識總結

  1. 數據庫範式

數據庫範式,是設計關係型數據庫時的規範要求,範式越高,數據冗餘越小。

 

Mysql數據庫的設計爲什麼要用到範式?

答:mysql屬於關係型數據庫,是關係型數據就會存在空間浪費,而範式的終極目標就是減少數據冗餘,節省空間,所以在設計mysql數據庫時要用到範式。

 

常用的三種範式?

1NF:列不可分(字段數據要具有原子性,不可再分),eg:【聯繫人】(姓名,性別,電話),一個聯繫人有家庭電話和公司電話,那麼這種表結構設計就沒有達到 1NF;

 

2NF:無部分依賴保證完全依賴。eg:訂單明細表【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName),Discount(折扣),Quantity(數量)完全依賴(取決)於主鍵(OderID,ProductID),而 UnitPrice,ProductName 只依賴於 ProductID,不符合2NF;

 

3NF:無傳遞依賴(非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的情況),eg:訂單表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主鍵是(OrderID),CustomerName,CustomerAddr,CustomerCity 直接依賴的是 CustomerID(非主鍵列),而不是直接依賴於主鍵,它是通過傳遞才依賴於主鍵,所以不符合 3NF。

 

範式有六層,在設計mysql數據庫時,會用到哪幾層?爲什麼?

只會用到範式中的前三層。因爲範式的終極目標是減少數據冗餘,節省空間,也就是說範式也爲解決空間問題,而不會考慮效率問題。而在設計mysql數據庫時,不僅僅要考慮空間問題,還要保證效率問題,所以在設計mysql數據庫時,只有前三種範式需要滿足。

規範化越高,那麼產生的關係就越多,關係過多的直接結果就是導致表之間的連接操作越頻繁,而表之間的連接操作是性能較低的操作,直接影響到査詢的速度。(*****

 

爲什麼引入範式的逆規範化在查詢時,在某一個表中增加一個冗餘字段,代替表間的連接)

答:因爲規範化越高,那麼產生的關係就越多,關係過多的直接結果就是導致表之間的連接操作越頻繁,而表之間的連接操作是性能較低的操作,直接影響到査詢的速度,所以,對於査詢較多的應用,就需要根據實際情況運用逆規範化對數據進行設計,通過逆規範化來提高査詢的性能。

反規範的好處是降低連接操作的需求、降低外碼和索引的數目,還可能減少表的數目,相應帶來的問題是可能出現數據的完整性問題加快查詢速度,但會降低修改速度。因此,決定 做反規範時,一定要權衡利弊,仔細分析應用的數據存取需求和實際的性能特點,好的索引和 其他方法經常能夠解決性能問題,而不必採用反規範這種方法。

2、數據庫索引

索引是對數據庫中表一列或多列的值進行排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用B_TREE及其變種。索引加速了對數據的訪問,因爲存儲引擎不會再去掃描整張表得到需要的數據;相反,索引的引入,它從根節點開始,根節點保存了子節點的指針,存儲引擎會根據指針快速尋找數據。

 

(B樹相對於avl,i/o進行了優化 ,但是i/o和 遍歷方面相對於B+樹仍然是不足的)

上圖顯示了一種索引方式。左邊是數據庫中的數據表,有col1和col2兩個字段,一共有15條記錄;右邊是以col2列爲索引列的B_TREE索引,每個節點包含索引的鍵值和對應數據表地址的指針,這樣就可以通過B_TREE在 O(logn) 的時間複雜度內獲取相應的數據,這樣明顯地加快了檢索的速度。

 

1). 索引的底層實現原理和優化

  在數據結構中,我們最爲常見的搜索結構就是二叉搜索樹和AVL樹(高度平衡的二叉搜索樹,爲了提高二叉搜索樹的效率,減少樹的平均搜索長度)了。然而,無論二叉搜索樹還是AVL樹,當數據量比較大時,都會由於樹的深度過大而造成I/O讀寫過於頻繁,進而導致查詢效率低下,因此對於索引而言,多叉樹結構成爲不二選擇。特別地,B-Tree的各種操作能使B樹保持較低的高度,從而保證高效的查找效率。

 

(1). B-Tree(平衡多路查找樹)

 

B_TREE是一種平衡多路查找樹,是一種動態查找效率很高的樹形結構。B_TREE中所有結點的孩子結點的最大值稱爲B_TREE的階,B_TREE的階通常用m表示,簡稱爲m叉樹。一般來說,應該是m>=3。一顆m階的B_TREE或是一顆空樹,或者是滿足下列條件的m叉樹5點

 

*樹中每個結點最多有m個孩子結點;

 

*若根結點不是葉子節點,則根結點至少有2個孩子結點;

 

*除根結點外,其它結點至少有(m/2的上界)個孩子結點;

 

*結點的結構如下圖所示,其中,n爲結點中關鍵字個數,(m/2的上界)-1 <= n <= m-1;di(1<=i<=n)爲該結點的n個關鍵字值的第i個,且di< d(i+1);ci(0<=i<=n)爲該結點孩子結點的指針,且ci所指向的節點的關鍵字均大於或等於di且小於d(i+1);

 

*所有的葉結點都在同一層上,並且不帶信息(可以看作是外部結點或查找失敗的結點,實際上這些結點不存在,指向這些結點的指針爲空)。

 

B_TREE的查找類似二叉排序樹的查找,所不同的是B-樹每個結點上是多關鍵碼的有序表,在到達某個結點時,先在有序表中查找,若找到,則查找成功;否則,到按照對應的指針信息指向的子樹中去查找,當到達葉子結點時,則說明樹中沒有對應的關鍵碼。由於B_TREE的高檢索效率,B-樹主要應用在文件系統數據庫中,對於存儲在硬盤上的大型數據庫文件,可以極大程度減少訪問硬盤次數,大幅度提高數據檢索效率。

 

(2). B+Tree : InnoDB存儲引擎的索引實現

 

B+Tree是應文件系統所需而產生的一種B_TREE樹的變形樹。一棵m階的B+樹和m階的B_TREE的差異在於以下三點:

 

1n 子樹的結點中含有n個關鍵碼;

 

2所有的葉子結點中包含了全部關鍵碼的信息,及指向含有這些關鍵碼記錄的指針,且葉子結點本身依關鍵碼的大小自小而大的順序鏈接;

 

3非終端結點可以看成是索引部分(充當查找葉子節點索引的角色),結點中僅含有其子樹根結點中最大(或最小)關鍵碼。

 

  下圖爲一棵3階的B+樹。通常在B+樹上有兩個頭指針,一個指向根節點,另一個指向關鍵字最小的葉子節點。因此可以對B+樹進行兩種查找運算:一種是從最小關鍵字起順序查找,另一種是從根節點開始,進行隨機查找。

在B+樹上進行隨機查找、插入和刪除的過程基本上與B-樹類似。只是在查找時,若非終端結點上的關鍵碼等於給定值,並不終止,而是繼續向下直到葉子結點。因此,對於B+樹,不管查找成功與否,每次查找都是走了一條從根到葉子結點的路徑。

 

(3). 爲什麼說B+-tree比B 樹更適合實際應用中操作系統的文件索引和數據庫索引?****重中之重****

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

 

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

 

 數據庫索引採用B+樹而不是B樹的主要原因:B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷,而且在數據庫中基於範圍的查詢是非常頻繁的,而B樹只能中序遍歷所有節點,效率太低。

 

B+treeBtree的區別:****重中之重****

1n 子樹的結點中含有n個關鍵碼;

 

2)所有的葉子結點中包含了全部關鍵碼的信息,及指向含有這些關鍵碼記錄的指針,且葉子結點本身依關鍵碼的大小自小而大的順序鏈接;

 

  1. 非終端結點可以看成是索引部分(充當查找葉子節點索引的角色),結點中僅含有其子樹根結點中最大(或最小)關鍵碼。

 

  1. B+樹上有兩個頭指針,一個指向根節點,另一個指向關鍵字最小的葉子節點。因此可以對B+樹進行兩種查找運算:一種是從最小關鍵字起順序查找,另一種是從根節點開始,進行隨機查找。即:B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷,而B樹只能中序遍歷所有節點,效率太低。

 

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

 

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

 

(4). 文件索引和數據庫索引爲什麼使用B+樹?

文件與數據庫都是需要較大的存儲,也就是說,它們都不可能全部存儲在內存中,故需要存儲到磁盤上。而所謂索引,則爲了數據的快速定位與查找,那麼索引的結構組織要儘量減少查找過程中磁盤I/O的存取次數,因此B+樹相比B樹更爲合適。數據庫系統巧妙利用了局部性原理與磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每個節點只需要一次I/O就可以完全載入,而紅黑樹這種結構,高度明顯要深的多,並且由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性。最重要的是,B+樹還有一個最大的好處:方便掃庫。B樹必須用中序遍歷的方法按序掃庫,而B+樹直接從葉子結點挨個掃一遍就完了,B+樹支持range-query非常方便,而B樹不支持,這是數據庫選用B+樹的最主要原因。

1.文件很大,不可能全部存儲在內存中,故要存儲到磁盤上

2.索引的結構組織要儘量減少查找過程中磁盤I/O的存取次數(爲什麼使用B-/+Tree,還跟磁盤存取原理有關。)

3.局部性原理磁盤預讀,預讀的長度一般爲頁(page)的整倍數,(在許多操作系統中,頁得大小通常爲4k)

4.數據庫系統巧妙利用了磁盤預讀原理,將一個節點的大小設爲等於一個頁,這樣每個節點只需要一次I/O就可以完全載入,(由於節點中有兩個數組,所以地址連續)。而紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性

 

2). 索引的優點

提高查詢速度

創建唯一性索引,確保數據的唯一性

可以加速表和表之間的連接,實現表和表之間的參照完整性

使用分組和排序子句進行數據檢索時,可以減少分組和排序的時間

全文檢索字段進行搜素優化

3). 什麼情況下設置了索引但無法使用?

https://www.cnblogs.com/LiLiliang/p/9960895.html

 

  1. 以“%(表示任意0個或多個字符)”開頭的LIKE語句,模糊匹配;

 

  1. OR語句前後沒有同時使用索引;

 

(3)數據類型出現隱式轉化(如varchar不加單引號的話可能會自動轉換爲int型);

(4)對於多列索引,必須滿足 最左匹配原則 (eg:多列索引col1、col2和col3,則 索引生效的情形包括 col1或col1,col2或col1,col2,col3)。

(5)數據量太小,查索引並不比全表掃描更快;

(6)where 子句裏對索引列上有數學運算,用不上索引

(7)where 子句裏對有索引列使用函數,用不上索引

4). 什麼樣的字段適合創建索引?

(1)經常作查詢選擇的字段

(2)經常作表連接的字段

 

(3)經常出現在order by, group by, distinct,join後面的字段

5). 創建索引時需要注意什麼?

非空字段:應該指定列爲NOT NULL,除非你想存儲NULL。在mysql中,含有空值的列很難進行查詢優化,因爲它們使得索引、索引的統計信息以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值;

 

取值離散大的字段:(變量各個取值之間的差異程度)的列放到聯合索引的前面,可以通過count()函數查看字段的差異值,返回值越大說明字段的唯一值越多字段的離散程度高;

 

索引字段越小越好:數據庫的數據存儲以頁爲單位一頁存儲的數據越多,一次IO操作獲取的數據越大效率越高。

 

考慮使用覆蓋索引如果索引包含滿足查詢的所有數據,就稱爲覆蓋索引。覆蓋索引是一種非常強大的工具,能大大提高查詢性能。對數據很少被更新的表,如果用戶經常只查詢其中的幾個字段,可以考慮在這幾個字段上建立索引,從而將表的掃描改變爲索引的掃描。

 

6). 索引的缺點

時間方面:創建索引和維護索引要耗費時間,具體地,當對錶中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度;

 

空間方面:索引需要佔物理空間。

7). 索引的分類

普通索引和唯一性索引:索引列的值的唯一性

 

單個索引和複合索引:索引列所包含的列數

(複合索引遇到範圍查詢(>、<、between、like)就停止匹配)

 

(複合索引滿足交換律,where a = 1 and b = 1 等價於 where b = 1 and a = 1,因爲查詢優化器會進行優化)

 

聚簇索引與非聚簇索引:聚簇索引的葉子節點就是數據節點,而非聚簇索引的葉子節點仍然是索引節點,只不過有指向對應數據塊的指針。

 

***************************************************************************

1首先,我們要認識到聚簇索引和非聚簇索引的劃分依據是什麼 ?

InnoDB 會使用聚簇索索引來保存數據,而非聚簇索引的目的僅僅是加快查詢速度

2)在第一點認知基礎上,我們就可以知道:

  • 聚簇索引是唯一的,一個 InnoDB 表只有一個聚簇索引,而且一定會有一個聚簇索引,如果不存在,Innodb 存儲引擎會自動添加一個
  • 非聚簇所以可以有多個,而且只能由用戶自己添加,InnoDB 默認並不會創建任何非聚簇索引

3非聚簇索引中一定包含了聚簇索引的列值,但反過來卻不存在。

因此,使用非聚簇索引查詢數據一定會用到聚簇索引,但反過來卻不存在。

***************************************************************************

 

8). 主鍵、自增主鍵、主鍵索引與唯一索引概念區別

 

主鍵:指字段唯一、不爲空值的列;

 

主鍵索引:指的就是主鍵,主鍵是索引的一種,是唯一索引的特殊類型。創建主鍵的時候,數據庫默認會爲主鍵創建一個唯一索引;

 

自增主鍵:字段類型爲數字、自增、並且是主鍵;

 

唯一索引:索引列的值必須唯一,但允許有空值。主鍵是唯一索引,這樣說沒錯;但反過來說,唯一索引也是主鍵就錯誤了,因爲唯一索引允許空值,主鍵不允許有空值,所以不能說唯一索引也是主鍵。

 

9). 主鍵就是聚集索引嗎?主鍵和索引有什麼區別?

 

  主鍵是一種特殊的唯一性索引,其可以是聚集索引,也可以是非聚集索引。在SQLServer中,主鍵的創建必須依賴於索引,默認創建的是聚集索引,但也可以顯式指定爲非聚集索引。InnoDB作爲MySQL存儲引擎時,默認按照主鍵進行聚集,如果沒有定義主鍵,InnoDB會試着使用唯一的非空索引來代替。如果沒有這種索引,InnoDB就會定義隱藏的主鍵然後在上面進行聚集。所以,對於聚集索引來說,你創建主鍵的時候,自動就創建了主鍵的聚集索引。

3、數據庫事務

事務是一個不可分割的數據庫操作序列,也是數據庫併發控制的基本單位,事務的執行的結果必須使數據庫從一種一致性狀態變到另一種一致性狀態。

 

(1). 事務的特徵

 

原子性(Atomicity):事務所包含的一系列數據庫操作要麼全部成功執行,要麼全部回滾;

 

一致性(Consistency):事務的執行結果必須使數據庫從一個一致性狀態到另一個一致性狀態;

隔離性(Isolation):併發執行的事務之間不能相互影響;

 

持久性(Durability):事務一旦提交,對數據庫中數據的改變是永久性的。

 

(2). 事務併發帶來的問題

 

髒讀:一個事務讀取了另一個事務未提交的數據;

 

不可重複讀:不可重複讀的重點是修改,同樣條件下兩次讀取結果不同,也就是說,被讀取的數據可以被其它事務修改;

 

幻讀:幻讀的重點在於新增或者刪除,同樣條件下兩次讀出來的記錄數不一樣。

 

(3). 隔離級別

https://www.cnblogs.com/jian-gao/p/10795407.html

  隔離級別決定了一個session中的事務可能對另一個session中的事務的影響。ANSI標準定義了4個隔離級別,MySQL的InnoDB都支持,分別是:

 

READ UNCOMMITTED:最低級別的隔離,通常又稱爲dirty read,它允許一個事務讀取另一個事務還沒commit的數據,這樣可能會提高性能,但是會導致髒讀問題;

 

READ COMMITTED:在一個事務中只允許對其它事務已經commit的記錄可見,該隔離級別不能避免不可重複讀問題;

 

REPEATABLE READ:在一個事務開始後,其他事務對數據庫的修改在本事務中不可見,直到本事務commit或rollback。但是,其他事務的insert/delete操作對該事務是可見的,也就是說,該隔離級別並不能避免幻讀問題。在一個事務中重複select的結果一樣,除非本事務中update數據庫。

 

SERIALIZABLE:最高級別的隔離,只允許事務串行執行。

 

MySQL默認的隔離級別是REPEATABLE READ。

 

(4)、mysql的事務支持

 

MySQL的事務支持不是綁定在MySQL服務器本身,而是與存儲引擎相關:

 

MyISAM:不支持事務,用於只讀程序提高性能;

InnoDB:支持ACID事務、行級鎖、併發;

Berkeley DB:支持事務。

4、實踐中如何優化MySQL

  實踐中,MySQL的優化主要涉及SQL語句及索引的優化、數據表結構的優化、系統配置的優化和硬件的優化四個方面

(1)、SQL語句及索引的優化

1). SQL語句的優化

SQL語句的優化主要包括三個問題,即

(1)如何發現有問題的SQL

(2)如何分析SQL的執行計劃

(3)如何優化SQL

 

a. 怎麼發現有問題的SQL?(通過MySQL慢查詢日誌對有效率問題的SQL進行監控

 

MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。long_query_time的默認值爲10,意思是運行10s以上的語句。慢查詢日誌的相關參數。

 

  通過MySQL的慢查詢日誌,我們可以查詢出執行的次數多佔用的時間長的SQL、可以通過pt_query_disgest(一種mysql慢日誌分析工具)分析Rows examine(MySQL執行器需要檢查的行數)項去找出IO大的SQL以及發現未命中索引的SQL,對於這些SQL,都是我們優化的對象。

 

b. 通過explain查詢和分析SQL的執行計劃

 

使用 EXPLAIN 關鍵字可以知道MySQL是如何處理你的SQL語句的,以便分析查詢語句或是表結構的性能瓶頸。通過explain命令可以得到表的讀取順序、數據讀取操作的操作類型、哪些索引可以使用、哪些索引被實際使用、表之間的引用以及每張表有多少行被優化器查詢等問題。當擴展列extra出現Using filesort和Using temporay,則往往表示SQL需要優化了。

 

c. SQL語句的優化

 

※ 優化insert語句:一次插入多值;

 

※ 應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描;

 

※ 應儘量避免在 where 子句中對字段進行null值判斷,否則將導致引擎放棄使用索引而進行全表掃描;

 

※ 優化嵌套查詢:子查詢可以被更有效率的連接(Join)替代;(子查詢會產生臨時表)

 

※ 很多時候用 exists 代替 in 是一個好的選擇。

 

產生臨時表的情況:(******

https://www.cnblogs.com/hxphp/p/7651365.html

2)、索引優化

 

※ 建議在經常作查詢選擇的字段、經常作表連接的字段以及經常出現在order by、group by、distinct 後面的字段中建立索引。但必須注意以下幾種可能會引起索引失效的情形:

 

※ 以“%(表示任意0個或多個字符)”開頭的LIKE語句,模糊匹配;

 

※ OR語句前後沒有同時使用索引;

 

※ 數據類型出現隱式轉化(如varchar不加單引號的話可能會自動轉換爲int型);

 

※ 對於多列索引,必須滿足最左匹配原則(eg,多列索引col1、col2和col3,則 索引生效的情形包括col1或col1,col2或col1,col2,col3)。

 

(2). 數據庫表結構的優化

  數據庫表結構的優化包括選擇合適數據類型表的範式的優化表的垂直拆分表的水平拆分等手段。

 

(1). 選擇合適數據類型

 

使用較小的數據類型解決問題;

 

使用簡單的數據類型(mysql處理int要比varchar容易);

 

儘可能的使用not null 定義字段;

 

儘量避免使用text類型,非用不可時最好考慮分表;

 

(2). 表的範式的優化

 

  一般情況下,表的設計應該遵循三大範式。

(3). 表的垂直拆分

  把含有多個列的表拆分成多個表,解決表寬度問題,具體包括以下幾種拆分手段:

 

※ 把不常用的字段單獨放在同一個表中;

 

※ 把大字段獨立放入一個表中;

 

※ 把經常使用的字段放在一起;

 

這樣做的好處是非常明顯的,具體包括:拆分後業務清晰,拆分規則明確、系統之間整合或擴展容易、數據維護簡單。

(4). 表的水平拆分

表的水平拆分用於解決數據表中數據過大的問題,水平拆分每一個表的結構都是完全一致的。一般地,將數據平分到N張表中的常用方法包括以下兩種:

 

 對ID進行hash運算,如果要拆分成5個表,mod(id,5)取出0~4個值;

 針對不同的hashID將數據存入不同的表中;

表的水平拆分會帶來一些問題和挑戰,包括跨分區表的數據查詢、統計及後臺報表的操作等問題,但也帶來了一些切實的好處:

 

※ 表分割後可以降低在查詢時需要讀的數據和索引的頁數,同時也降低了索引的層數,提高查詢速度;

 

※ 表中的數據本來就有獨立性,例如表中分別記錄各個地區的數據或不同時期的數據,特別是有些數據常用,而另外一些數據不常用。

 

※ 需要把數據存放到多個數據庫中,提高系統的總體可用性(分庫,雞蛋不能放在同一個籃子裏)。

 

(3). 系統配置的優化

操作系統配置的優化:增加TCP支持的隊列數

 

mysql配置文件優化:Innodb緩存池設置(innodb_buffer_pool_size,推薦總內存的75%)和緩存池的個數(innodb_buffer_pool_instances)

 

(4). 硬件的優化

CPU:核心數多並且主頻高的

內存:增大內存

磁盤配置和選擇:磁盤性能

5、NOSQL數據庫 —— Redis

Redis是一款基於內存的且支持持久化、高性能的Key-Value NoSQL 數據庫,其支持豐富數據類型(string,list,set,sorted set,hash),常被用作緩存的解決方案。Redis具有以下顯著特點:

 

速度快,因爲數據存在內存中,類似於HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1);

 

支持豐富數據類型,支持string,list,set,sorted set,hash;

 

支持事務,操作都是原子性,所謂的原子性就是對數據的更改要麼全部執行,要麼全部不執行;

 

豐富的特性:可用於緩存,消息,按key設置過期時間,過期後將會自動刪除。

 

Redis作查詢緩存需要注意考慮以下幾個問題,包括防止髒讀、序列化查詢結果、爲查詢結果生成一個標識和怎麼使用四個問題,具體如下:

 

(1). 防止髒讀

 

  對一張表的查詢結果放在一個哈希結構裏,當對這個表進行修改、刪除或者更新時,刪除該哈希結構。對這張表所有的操作方法,使用註解進行標記。

 

  我們緩存了查詢結果,那麼一旦數據庫中的數據發生變化,緩存的結果就不可用了。爲了實現這一保證,可以在執行相關表的更新查詢(update,delete,insert)查詢前,讓相關的緩存過期。這樣下一次查詢時程序就會重新從數據庫中讀取新數據緩存到redis中。那麼問題來了,在執行一條insert前我怎麼知道應該讓哪些緩存過期呢?對於Redis,我們可以使用Hash結構,讓一張表對應一個Hash,所有在這張表上的查詢都保存到該Hash下。這樣當表數據發生變動時,直接讓Set過期即可。我們可以自定義一個註解,在數據庫查詢方法上通過註解的屬性註明這個操作與哪些表相關,這樣在執行過期操作時,就能直接從註解中得知應該讓哪些Set過期了。

 

(2). 序列化查詢結果

 

  利用JDK自帶的ObjectInputStream/ObjectOutputStream將查詢結果序列化成字節序列,即需要考慮Redis的實際存儲問題。

 

(3). 爲查詢結果生成一個標識

 

  被調用的方法所在的類名,被調用的方法的方法名,該方法的參數三者共同標識一條查詢結果。也就是說,如果兩次查詢調用的類名、方法名和參數值相同,我們就可以確定這兩次查詢結果一定是相同的(在數據沒有變動的前提下)。因此,我們可以將這三個元素組合成一個字符串做爲key,就解決了標識問題。

 

(4). 以 AOP 方式使用Redis

 

方法被調用之前,根據類名、方法名和參數值生成Key;

 

通過Key向Redis發起查詢;

 

如果緩存命中,則將緩存結果反序列化作爲方法調用的返回值 ,並將其直接返回;

如果緩存未命中,則繼續向數據庫中查詢,並將查詢結果序列化存入redis中,同時將查詢結果返回。

 

6、什麼是存儲過程?有哪些優缺點?

  存儲過程是事先經過編譯並存儲在數據庫中的一段SQL語句的集合。進一步地說,存儲過程是由一些T-SQL語句組成的代碼塊,這些T-SQL語句代碼像一個方法一樣實現一些功能(對單表或多表的增刪改查),然後再給這個代碼塊取一個名字,在用到這個功能的時候調用他就行了。存儲過程具有以下特點:

 

存儲過程只在創建時進行編譯,以後每次執行存儲過程都不需再重新編譯,而一般 SQL 語句每執行一次就編譯一次,所以使用存儲過程可提高數據庫執行效率;

 

當SQL語句有變動時,可以只修改數據庫中的存儲過程而不必修改代碼;

 

減少網絡傳輸,在客戶端調用一個存儲過程當然比執行一串SQL傳輸的數據量要小;

 

通過存儲過程能夠使沒有權限的用戶在控制之下間接地存取數據庫,從而確保數據的安全。

7、簡單說一說drop、delete與truncate的區別

SQL中的drop、delete、truncate都表示刪除,但是三者有一些差別:

 

Delete用來刪除表的全部或者一部分數據行,執行delete之後,用戶需要提交(commmit)或者回滾(rollback)來執行刪除或者撤銷刪除, delete命令會觸發這個表上所有的delete觸發器;

 

Truncate刪除表中的所有數據,這個操作不能回滾,也不會觸發這個表上的觸發器,TRUNCATE比delete更快,佔用的空間更小;

 

Drop命令從數據庫中刪除表,所有的數據行,索引和權限也會被刪除,所有的DML觸發器也不會被觸發,這個命令也不能回滾。

 

因此,在不再需要一張表的時候,用drop;在想刪除部分數據行時候,用delete;在保留表而刪除所有數據的時候用truncate。

  1. 什麼叫視圖?遊標是什麼?

https://baijiahao.baidu.com/s?id=1623365360611120859&wfr=spider&for=pc

視圖是一種虛擬的表,通常是有一個表或者多個表的行或列的子集,具有和物理表相同的功能,可以對視圖進行增,刪,改,查等操作。特別地,對視圖的修改不影響基本表。相比多表查詢,它使得我們獲取數據更容易。

 

  遊標是對查詢出來的結果集作爲一個單元來有效的處理。遊標可以定在該單元中的特定行,從結果集的當前行檢索一行或多行。可以對結果集當前行做修改。一般不使用遊標,但是需要逐條處理數據的時候,遊標顯得十分重要。

 

  在操作mysql的時候,我們知道MySQL檢索操作返回一組稱爲結果集的行。這組返回的行都是與 SQL語句相匹配的行(零行或多行)。使用簡單的 SELECT語句,例如,沒有辦法得到第一行、下一行或前 10行,也不存在每次一行地處理所有行的簡單方法(相對於成批地處理它們)。有時,需要在檢索出來的行中前進或後退一行或多行。這就是使用遊標的原因。遊標(cursor)是一個存儲在MySQL服務器上的數據庫查詢,它不是一條 SELECT語句,而是被該語句檢索出來的結果集。在存儲了遊標之後,應用程序可以根據需要滾動或瀏覽其中的數據。遊標主要用於交互式應用,其中用戶需要滾動屏幕上的數據,並對數據進行瀏覽或做出更改。

9、什麼是觸發器?

觸發器是與表相關的數據庫對象,在滿足定義條件時觸發,並執行觸發器中定義的語句集合。觸發器的這種特性可以協助應用在數據庫端確保數據庫的完整性。

10、MySQL中的悲觀鎖與樂觀鎖的實現

  悲觀鎖與樂觀鎖是兩種常見的資源併發鎖設計思路,也是併發編程中一個非常基礎的概念。

 

  1. . 悲觀鎖

悲觀鎖的特點是先獲取鎖,再進行業務操作,即“悲觀”的認爲所有的操作均會導致併發安全問題,因此要先確保獲取鎖成功再進行業務操作。通常來講,在數據庫上的悲觀鎖需要數據庫本身提供支持,即通過常用的select … for update操作來實現悲觀鎖。當數據庫執行select … for update時會獲取被select中的數據行的行鎖,因此其他併發執行的select … for update如果試圖選中同一行則會發生排斥(需要等待行鎖被釋放),因此達到鎖的效果。select for update獲取的行鎖會在當前事務結束時自動釋放,因此必須在事務中使用。

  這裏需要特別注意的是,不同的數據庫對select… for update的實現和支持都是有所區別的,例如oracle支持select for update no wait,表示如果拿不到鎖立刻報錯,而不是等待,mysql就沒有no wait這個選項。另外,mysql還有個問題是: select… for update語句執行中所有掃描過的行都會被鎖上,這一點很容易造成問題。因此,如果在mysql中用悲觀鎖務必要確定使用了索引,而不是全表掃描。

 

(2). 樂觀鎖(方式1:版本號;方式2:時間戳

 

  樂觀鎖的特點先進行業務操作,只在最後實際更新數據時進行檢查數據是否被更新過,若未被更新過,則更新成功;否則,失敗重試。樂觀鎖在數據庫上的實現完全是邏輯的,不需要數據庫提供特殊的支持。一般的做法是在需要鎖的數據上增加一個版本號或者時間戳,然後按照如下方式實現:

  樂觀鎖是否在事務中其實都是無所謂的,其底層機制是這樣:在數據庫內部update同一行的時候是不允許併發的,即數據庫每次執行一條update語句時會獲取被update行的寫鎖,直到這一行被成功更新後才釋放。因此在業務操作進行前獲取需要鎖的數據的當前版本號,然後實際更新數據時再次對比版本號確認與之前獲取的相同,並更新版本號,即可確認這其間沒有發生併發的修改。如果更新失敗,即可認爲老版本的數據已經被併發修改掉而不存在了,此時認爲獲取鎖失敗,需要回滾整個業務操作並可根據需要重試整個過程

 

(3). 悲觀鎖與樂觀鎖的應用場景

 

  一般情況下,讀多寫少更適合用樂觀鎖,讀少寫多更適合用悲觀鎖。樂觀鎖在不發生取鎖失敗的情況下開銷比悲觀鎖小,但是一旦發生失敗回滾開銷則比較大,因此適合用在取鎖失敗概率比較小的場景,可以提升系統併發性能。

11、JDBC 對事務的支持

  對於JDBC而言,每條單獨的語句都是一個事務,即每個語句後都隱含一個commit。實際上,Connection 提供了一個auto-commit的屬性來指定事務何時結束。當auto-commit爲true時,當每個獨立SQL操作的執行完畢,事務立即自動提交,也就是說,每個SQL操作都是一個事務;當auto-commit爲false時,每個事務都必須顯式調用commit方法進行提交,或者顯式調用rollback方法進行回滾。auto-commit默認爲true。

  爲了能夠將多條SQL當成一個事務執行,必須首先通過Connection關閉auto-commit模式,然後通過Connection的setTransactionIsolation()方法設置事務的隔離級別,最後分別通過Connection的commit()方法和rollback()方法來提交事務和回滾事務。

12、MySQL存儲引擎中的MyISAM和InnoDB區別詳解

  在MySQL 5.5之前,MyISAM是mysql的默認數據庫引擎,其由早期的ISAM(Indexed Sequential Access Method:有索引的順序訪問方法)所改良。雖然MyISAM性能極佳,但卻有一個顯著的缺點: 不支持事務處理。不過,MySQL也導入了另一種數據庫引擎InnoDB,以強化參考完整性與併發違規處理機制,後來就逐漸取代MyISAM。

 

InnoDB與傳統的ISAM、MyISAM相比,InnoDB的最大特色就是支持ACID兼容的事務功能。具體地,MyISAM與InnoDB作爲MySQL的兩大存儲引擎的差異主要包括:

 

存儲結構:每個MyISAM在磁盤上存儲成三個文件:第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義,數據文件的擴展名爲.MYD (MYData),索引文件的擴展名是.MYI (MYIndex)。InnoDB所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操作系統文件的大小,一般爲2GB。

 

存儲空間:MyISAM可被壓縮,佔據的存儲空間較小,支持靜態表、動態表、壓縮表三種不同的存儲格式。InnoDB需要更多的內存和存儲,它會在主內存中建立其專用的緩衝池用於高速緩衝數據和索引。

 

可移植性、備份及恢復:MyISAM的數據是以文件的形式存儲,所以在跨平臺的數據轉移中會很方便,同時在備份和恢復時也可單獨針對某個表進行操作。InnoDB免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了。

 

事務支持:MyISAM強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。InnoDB提供事務、外鍵等高級數據庫功能,具有事務提交、回滾和崩潰修復能力。

 

AUTO_INCREMENT:在MyISAM中,可以和其他字段一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,它可以根據前面幾列進行排序後遞增。InnoDB中必須包含只有該字段的索引,並且引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。

 

表鎖差異:MyISAM只支持表級鎖,用戶在操作MyISAM表時,select、update、delete和insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的數據。InnoDB支持事務和行級鎖。行鎖大幅度提高了多用戶併發操作的新能,但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。

 

全文索引:MyISAM支持 FULLTEXT類型的全文索引;InnoDB不支持FULLTEXT類型的全文索引,但是innodb可以使用sphinx插件支持全文索引,並且效果更好。

 

表主鍵:MyISAM允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。對於InnoDB,如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。

 

表的具體行數:MyISAM保存表的總行數,select count() from table;會直接取出出該值;而InnoDB沒有保存表的總行數,如果使用select count() from table;就會遍歷整個表,消耗相當大,但是在加了wehre條件後,myisam和innodb處理的方式都一樣。

 

CURD操作:在MyISAM中,如果執行大量的SELECT,MyISAM是更好的選擇。對於InnoDB,如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數據的表,最好使用truncate table這個命令。

 

外鍵:MyISAM不支持外鍵,而InnoDB支持外鍵。

 

  通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了,原因是InnoDB自身很多良好的特點,比如事務支持、存儲過程、視圖、行級鎖、外鍵等等。尤其在併發很多的情況下,相信InnoDB的表現肯定要比MyISAM強很多。另外,必須需要注意的是,任何一種表都不是萬能的,合適的纔是最好的,才能最大的發揮MySQL的性能優勢。如果是不復雜的、非關鍵的Web應用,還是可以繼續考慮MyISAM的,這個具體情況具體考慮。

 

 

1. InnoDB支持事務,MyISAM不支持,對於InnoDB每一條SQL語言都默認封裝成事務,自動提交,這樣會影響速度,所以最好把多條SQL語言放在begin和commit之間,組成一個事務; 

 

2. InnoDB支持外鍵,而MyISAM不支持。對一個包含外鍵的InnoDB錶轉爲MYISAM會失敗; 

 

  3.     MyISAM是非聚集索引,也是使用B+Tree作爲索引結構,索引和數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是獨立的。

 

       InnoDB是聚集索引,的B+樹主鍵索引的葉子節點就是數據文件,輔助索引的葉子節點是主鍵的值;而MyISAM的B+樹主鍵索引和輔助索引的葉子節點都是數據文件的地址指針。

 

  1. InnoDB不保存表的具體行數,執行select count(*) from table時需要全表掃描。而MyISAM用一個變量保存了整個表的行數,執行上述語句時只需要讀出該變量即可,速度很快;

 

  1. InnoDB支持表、行(默認)級鎖,而MyISAM支持表級
  2. InnoDB表必須有主鍵(用戶沒有指定的話會自己找或生產一個主鍵),而Myisam可以沒有;
  3. Innodb存儲文件有frm、ibd,而Myisam是frm、MYD、MYI

Innodb:frm是表定義文件,ibd是數據文件

Myisam:frm是表定義文件,myd是數據文件,myi是索引文件

 

  1. MySQL中的鎖

https://blog.51cto.com/13764714/2385447?source=dra

 

1)MySQL各存儲引擎使用了三種類型(級別)的鎖定機制:

  • 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低;
  • 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高;
  • 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

 

https://blog.csdn.net/qq_37933685/article/details/80717515

 MySQL中的鎖機制,按粒度分爲行級鎖,頁級鎖,表級鎖.

 其中按用法還分爲共享鎖和排他鎖.

 樂觀鎖

 悲觀所

  1. InnoDB使用的七種鎖

https://www.jianshu.com/p/74557387e3fd

自增鎖

自增鎖是一種特殊的表級別鎖(table-level lock),專門針對事務插入AUTO_INCREMENT類型的列。最簡單的情況,如果一個事務正在往表中插入記錄,所有其他事務的插入必須等待,以便第一個事務插入的行,是連續的主鍵值。

 

共享/排他鎖

共享/排它鎖是標準的行級鎖(row-level locking)

事務拿到某一行記錄的共享S鎖,纔可以讀取這一行;

事務拿到某一行記錄的排它X鎖,纔可以修改或者刪除這一行;

多個事務可以拿到一把S鎖,讀讀可以並行;

而只有一個事務可以拿到X鎖,寫寫/讀寫必須互斥;

共享/排它鎖的潛在問題是,不能充分的並行,解決思路是數據多版本

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章