MySql數據庫知識點總結

MySql數據庫

1.什麼是索引?

索引是對數據表中一列或者多列的值進行排序的數據結構,用來加快數據庫檢索數據的速度。mysql

2.MySql索引的類別有哪些?

從數據結構的角度算法

  • B+樹索引:最多見的索引類型,基於B+樹數據結構(InnoDB和MyISAM引擎、memory引擎)
  • Hash索引:基於hash表,因此只支持精確查找(時間複雜度O(1)),不支持範圍查找(Memory引擎)
  • 全文索引:主要用來查找文本中的關鍵字(MyISAM,InnoDB)
  • 空間索引:基於R樹實現,用於地理數據存儲(MyISAM)

從物理存儲角度sql

  • 聚簇索引:表中記錄的物理順序與鍵值的索引順序相同,數據庫主鍵就是聚簇索引
  • 非聚簇索引:表中記錄的物理順序與鍵值的索引順序不相同 Mysql中InnoDB引擎的主鍵索引爲聚簇索引,MyISAM存儲引擎採用非聚簇索引

從邏輯角度數據庫

  • 普通索引:最基本的索引,沒有任何限制
  • 惟一索引:惟一索引是在表上一個字段或者多個字段組合創建的索引,這個字段或者這些字段的組合在表中不容許重複
  • 主鍵索引:是惟一索引的一種特殊狀況,在表的主鍵上創建索引
  • 組合索引:基於多個字段建立的索引成爲組合索引,一個查詢能夠只使用索引中的一部分,但必須是最左側部分,好比索引 index(a,b,c),那麼只能夠支持a|a,b|a,b,c進行查找

3.MySql數據庫索引爲何用B+樹而不是B樹?

回答這個問題,首先要知道什麼是B樹,什麼是B+樹服務器

  • 一顆m階(階數表明一棵樹的節點最多能夠擁有的子節點數,3階B數的節點最多擁有3個子節點)的B樹具備如下性質:數據結構

    • 根節點至少有兩個子女
    • 每一箇中間節點都包含k-1個元素和k個孩子,ceil(m/2)<=k<=m
    • 每一個葉子節點都包含k-1個元素,ceil(m/2)<=k<=m
    • 每一個葉子節點都在同一層
    • 每一個節點中元素按照從小到大的順序排列,且k-1個元素正好是k個孩子元素的值域分劃
  • 一顆m階的B+樹具備如下性質:併發

    • 有k個子樹的中間節點包含有k個元素(B樹是k-1個元素),每一個元素不保存數據,只用來索引,全部的數據都保存在葉子節點
    • 葉子節點包含了所有元素的信息,及指向這些元素記錄的指針,且葉子節點自己依照關鍵字的大小從小到大順序鏈接
    • 全部的中間節點元素都同時存在於子節點,是子節點中最大(或最小)元素

影響索引查找速度的最主要的就是磁盤IO次數,而最壞狀況下磁盤IO次數等於索引樹的高度,因此咱們須要索引樹越「矮胖」越好 之因此使用B+樹作爲數據庫索引的數據結構,是由於B+樹相較於B樹有如下幾個優勢: 主要緣由是,B樹在提升磁盤IO性能的同時並無能解決元素遍歷效率低下的問題性能

  • B+樹更少的IO次數:B+樹的中間節點不存儲衛星數據,意味着一樣大小的磁盤頁能夠容納更多的節點(每次磁盤IO能夠讀取到更多的節點),在查詢時IO次數會更少
  • B+樹具備更穩定的查詢性能:B+樹的查詢最終必須查找葉子節點,查詢性能更加穩定
  • B+樹的範圍查詢性能更好:B+樹葉子節點造成有序鏈表,範圍查詢性能更好(B樹則須要不停的中序遍歷,B+樹直接查找葉子節點的有序鏈表便可)

4.數據庫爲何用B+樹而不用紅黑樹?

  • 紅黑樹IO次數更多:磁盤IO的最大次數由樹的高度決定,紅黑樹是二叉樹,一樣數據量的狀況下,紅黑樹的高度會比B+樹高出許多
  • 沒有很好的利用磁盤預讀特性:紅黑樹沒有很好得利用磁盤預讀特性(磁盤不是嚴格的按需讀取,而是每次都會預讀一部分數據進內存,依據是局部性原理,即當一個數據被用到時,其附近的數據一般會立刻被使用) 紅黑樹邏輯上很近的節點,物理上可能很遠,沒法很好的利用局部性原理進行預讀;B+樹的非葉子節點不存儲衛星數據,只作爲索引,相對來講一樣的磁盤頁能夠存儲更多的節點,節點大小設置爲磁盤頁的大小,充分利用磁盤預讀

5.通常什麼狀況下使用索引?

  • 主鍵的列上
  • 常常鏈接的列上,加快鏈接的速度(join)
  • 常用排序的列上(order by)
  • 常用在where子句中的列上(where)

6.什麼狀況下索引會失效?

  • 查詢條件中使用or時,若是兩個字段有一個沒有索引,則索引失效
  • 組合索引,不知足最左前綴匹配
  • like的模糊查詢以'%'開頭,例如 like "%w"會致使索引失效
  • 列爲字符串,作條件查詢時字符串常量未加引號
  • mysql預計使用全表掃描比使用索引要快

7.InnoDB和MyISAM的區別?

  • InnoDB支持事務,MyISAM不支持事務
  • InnoDB支持外鍵,MyISAM不支持外鍵
  • InnoDB是聚簇索引,MyISAM是非聚簇索引
  • InnoDB不保存表的具體行數,須要的時候要掃描全表;MyISAM專門有一個變量來保存表的行數,執行時只須要讀出該變量便可,速度很快
  • InnoDB最小鎖粒度是行鎖,MyISAM最小鎖粒度是表鎖,一個更新語句會鎖住整張表,致使其餘查詢和更新被阻塞

8.怎麼修改數據庫引擎?

alert table xx type=xxx線程

9.數據庫中有哪些鎖?

  • 樂觀鎖:樂觀鎖在操做數據時很是樂觀,認爲別人不會同時修改數據,所以樂觀鎖不會上鎖,只是在執行更新的時候判斷一下在此期間別人是否修改了數據,若是修改了則放棄操做,不然執行操做
  • 悲觀鎖:悲觀鎖在操做數據時比較悲觀,認爲別人會同時修改數據,所以操做數據時會對數據上鎖,直到操做完成纔會釋放鎖,上鎖期間其餘人不能操做該數據
  • 共享鎖(Share Lock,S鎖):又被稱爲讀鎖,是悲觀鎖的一種實現方式,多個事務對於同一數據共享一把鎖,可是隻能讀不能修改,也能夠再對該數據加共享鎖,但不能加排他鎖
  • 排他鎖(Exclusive Lock,X鎖):又被稱爲寫鎖,是悲觀鎖的一種實現方式,若某事務對數據A上排他鎖,則其餘事務不能併發讀取該數據,而且不能再對該數據加任何類型的鎖,得到排他鎖的事務便可讀取,又可修改

10.樂觀鎖的實現方式有哪些?

版本號機制和CAS算法設計

  • 版本號機制:在數據表中加一個版本號字段version,表示數據被修改的次數,每被修改一次版本號就會加一,讀取數據時會一併讀取這個version字段,當提交更新時,只有當提交數據的版本號大於數據庫當前的版本號,纔會執行更新;不然認爲是過時數據
  • volatile+CAS算法:CAS算法涉及到三個操做數
    • 須要讀寫的內存值V(存儲在主內存中,線程須要從主內存中讀取,備份到本地)
    • 進行比較的值A(線程從主內存中讀取的V的值的本地備份A)
    • 想要寫入的新值B(用來更新主內存V的值,更新完之後,V=B) 流程:每一個線程讀取主內存的值(V)後會備份一個副本到本地(A),當執行更新時須要判斷V和A的值是否相等,若是相等則用新值B來更新V,使得V=B;不然不予更新,而且不斷地重試(自選操做)

CAS算法存在的問題:

  • ABA問題:一個線程將內存值從A改成B,另一個線程又將內存值從B改爲A(解決方法:在加上版本號)
  • 循環時間長開銷大:自旋CAS(不成功一直循環到成功)若是長時間不成功,會給CPU帶來很是大的執行開銷(限制自旋次數)
  • CAS的原子操做只能針對一個共享變量(把多個共享變量合併成一個共享變量操做)

11.何時會對行或者表加鎖?

InnoDB引擎即支持行鎖也支持表鎖,只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然將使用表級鎖

12.什麼是事務?事物的隔離級別有哪些?

事務是邏輯上的一組操做,要麼都執行,要麼都不執行 事物的特性(ACID):原子性,一致性,隔離性,持久性

  • 原子性:事務是最小的執行單位,不可分割
  • 一致性:是指事務使系統從一個一致的狀態轉換到另外一個一致的狀態,一致性是對數據可見性的約束,保證在一個事務中的屢次操做的數據中間狀態對其餘事務不可見的
  • 隔離性:事務之間互不干擾,彼此獨立
  • 持久性:事務提交後,對系統的影響是永久的

併發事務帶來的問題:

  • 髒讀(Dirty Read):當一個事務正在訪問數據並對數據進行了修改,可是這個修改尚未提交到數據庫;此時其餘事務訪問了這個數據,此時訪問到的數據爲「髒數據」,依據「髒數據」所作的操做多是不正確的

  • 丟失修改(Lost to modify):指在一個事務讀取一個數據時,另一個事務也訪問了該數據,那麼在第一個事務修改了數據以後,另外一個事務也對該數據進行了修改,致使前一個事物的修改丟失

  • 不可重複讀(Unrepeatable read):指在同一個事務內屢次訪問同一數據,在兩次訪問該數據之間,有其餘的事務訪問該數據,並對該數據進行了修改,致使同一事務內對同一數據的訪問結果不一致

  • 幻讀(Phantom read):一個事務讀取了幾行數據,隨後另一個併發事務插入了一些數據,致使前一個事務再次訪問該數據時,多出了一部分的數據

    併發事務帶來的問題須要數據庫提供事務間的隔離機制來實現,實現隔離機制的方法主要有:

    • 加讀寫鎖
    • 一致性快照,即MVCC

事務隔離級別

  • READ-UNCOMMITED(讀取未提交):最低的隔離級別,事務能夠讀取其餘併發事務還沒有提交的數據變動,可能會致使髒讀、幻讀、不可重複讀
  • READ-COMMITED(讀取已提交):一個事務只能讀取併發事務已提交的數據,能夠阻止髒讀,可是幻讀和不可重複度仍有可能發生
  • REPEATABLE-READ(可重複讀):在一個事務內對同一數據的屢次讀取結果是一致的,可是沒法避免產生幻讀
  • SERIALIZABLE(可串行化):最高的隔離級別,徹底服從ACID,該級別能夠防止髒讀、幻讀、不可重複讀

13.mysql的主從複製如何實現的?

mysql的主從複製主要涉及到三個線程:

  • 主節點binlog線程:負責將主服務器上的數據更改寫入到二進制日誌中(Binary log)
  • 從節點I/O線程:負責從主服務器讀取二進制日誌,並寫入到從服務器的中繼日誌(Relay log)
  • 從節點SQL線程:負責讀取中繼日誌,解析出服務器已經執行的數據更改並在從服務器中重放

14.什麼是MVCC?MVCC是怎麼實現的?

MVCC:多版本併發控制,InnoDB存儲引擎默認隔離級別是Repeatable Read(可重複讀),MVCC是行級鎖的一種實現,MVCC在Read Commited和Repeatable隔離級別下生效

**實現原理:**MVCC是經過在每行的後面保存兩個隱藏的列來實現的,一個保存行的建立時間,一個保存行的過時時間,保存的並非實際上的時間,而是系統版本號,每開始一個事務,系統版本號就會加一,同時這個系統版本號會做爲事務的版本號,用來和每行記錄的版本號進行比較

  • Select:InnoDB查詢返回知足的條件是:建立時間<=當前事務版本<過時時間或者過時時間未定義
    • 記錄的建立時間小於等於當前事務的版本號(確保當前事務查詢的結果是要麼在事務開始前就存在的,要麼是事務本身插入或者修改過的)
    • 記錄的過時時間要麼未定義要麼大於當前事務的版本號(確保事務讀取到的行在事務開始前未過時)
  • insert:InnoDB每插入一個新的行,保存當前事務版本號做爲開始時間
  • update:InnoDB執行update其實是插入一條新紀錄,並將原紀錄的過時時間設置爲當前事務版本號
  • delete:InnoDB執行delete時,刪除的行的過時時間設置爲當前事務版本號

15.爲何(InnoDB)推薦使用自增列作主鍵?

由於InnoDB使用聚簇索引,數據記錄自己就存儲在B+樹的葉子節點上,且按照主鍵由小到大順序排列,這就要求每一個葉子節點(大小爲一個內存頁或者磁盤頁大小)中的關鍵字都是順序排列的,若是使用自增主鍵的話,那麼每次插入新的數據只須要根據其主鍵將他插入到適當的節點和位置,若是頁面達到裝載因子(InnoDB是 15/16),那麼就會開闢一個新的頁來存儲,這樣是效率很高的,並且獲得的也會是一個緊湊的索引結構,也不會增長不少開銷在索引上;

若是不適用自增列作主鍵,好比使用身份證號或者學號之類的作主鍵的話,那麼每次插入新的記錄對應的主鍵基本上能夠看做是隨機的,那麼在找他的插入位置的時候就會帶來不少沒必要要的開銷,好比有些頁面已經回寫到磁盤上了,可是要作插入可能還要再次讀取這個頁面,就帶來了不少額外的開銷,而且頻繁的移動、分頁可能會致使索引的結構不夠緊湊,有大量的空間碎片得不到利用

因此通常都推薦使用自增列作主鍵

16.數據庫分庫分表

17.數據庫三範式?有哪些反範式的設計?

  • 第一範式:強調列的原子性,即列不能再分爲其餘幾列
  • 第二範式:首先要知足第一範式,其次須要知足表必須有一個主鍵,非主鍵列要徹底依賴於主鍵,而不能只依賴於主鍵的一部分
  • 第三範式:首先知足第二範式,在第二範式的基礎上消除傳遞依賴,即非主鍵列要直接依賴於主鍵,不能夠傳遞依賴

18.Explaxin用法?慢查詢?

19.join 和 left join、right join 的區別

相關文章
相關標籤/搜索