數據庫面經


一、Mysql的超鍵,候選鍵,主鍵,外鍵:

  (1)超鍵:在關系中能唯一標識元組的屬性集稱為超鍵,可以區分表中每一行記錄的屬性集(單個屬性,多個屬性組成也行)

    如:在一個學生的表中,假設有“學號”、“姓名”、“相關信息”、“生日”等字段, 其中學號是唯一的,那么(學號)是一個超鍵,同時(學號,姓名,生日)的組合也是唯一的,所以也可以為一個超鍵。反正記住一點,就是根據這些屬性可以唯一確定一名學生的,就是超鍵。

  (2)候選鍵:候選鍵是在超鍵的基礎上定義的,在要求可以區分每一行的基礎上,同時是最小唯一的,即候選鍵中刪除任何一個屬性后就不能再區分每一行。

  (3)主鍵:從候選鍵中選出一個鍵就能區分每一行的就是主鍵.

  (4)外鍵:在關系模式(表)R中,屬性a是其他模式的主鍵,則a是關系模式R中的外鍵.

二、數據庫的索引:

  表Employee(Name,Age,Address)

  查詢語句:SELECT * FROM Employee WHERE Name = 'Jesus'

  若無索引:運行這個查詢,在查找名字為Jesus的雇員的過程中,數據庫不得不從Employee表中的每一行並確定雇員的名字(Name)是否為 ‘Jesus’。由於我們想要得到每一個名字為Jesus的雇員信息,在查詢到第一個符合條件的行后,不能停止查詢,因為可能還有其他符合條件的行。所以,必須一行一行的查找直到最后一行-這就意味數據庫不得不檢查上千行數據才能找到所以名字為Jesus的雇員。這就是所謂的全表掃描

  使用索引如何提高性能:使用索引的全部意義就是通過縮小一張表中需要查詢的記錄/行的數目來加快搜索的速度。索引基本上是用來存儲列值的數據結構,這使查找這些列值更加快速。如果索引使用最常用的數據結構-B+樹-那么其中的數據是有序的。有序的列值可以極大的提升性能。我們在Name這一列上創建一個索引。這意味着當我們用之前的SQL查找姓名是‘Jesus’的雇員時,不需要再掃描全表。而是用索引查找去查找名字為‘Jesus’的雇員,因為索引已經按照按字母順序排序。索引已經排序意味着查詢一個名字會快很多,因為名字少字母為‘J’的員工都是排列在一起的。另外重要的一點是,索引同時存儲了表中相應行的指針以獲取其他列的數據。

   創建索引:CREATE INDEX name_index ON Employee (Employee_Name)

   創建聯合索引:CREATE INDEX name_index ON Employee (Employee_Name, Employee_Age)

(1)什么是索引:一個索引是存儲的表中一個特定列的值數據結構(最常見的是B+Tree和hash表)。索引是在表的列上創建。所以,要記住的關鍵點是索引包含一個表中列的值,並且這些值存儲在一個數據結構中。請記住記住這一點:索引是一種數據結構 。

  1、MySQL的基本存儲結構:頁,記錄都存儲在頁里面。

   1)各個數據頁可以組成一個雙向鏈表。

   2)每個數據頁中的行記錄組成單向鏈表。

   3)每個數據頁都會為存儲在它里邊兒的記錄生成一個頁目錄,在通過主鍵查找某條記錄的時候可以在頁目錄中使用二分法快速定位到對應的槽,然后再遍歷該槽對應分組中的記錄即可快速找到指定的記錄

   4)以其他列(非主鍵)作為搜索條件:只能從最小記錄開始依次遍歷單鏈表中的每條記錄。

  2、為什么沒有任何優化的查詢慢:

   1)需要遍歷雙向鏈表,找到所在的頁

   2)從所在的頁內中查找相應的記錄

   3)由於不是根據你主鍵查詢,只能遍歷所在的頁的單鏈表。

  3、索引里存的是什么

   數據庫索引並不存儲這個表中其他列(字段)的值。舉例來說,如果我們在Name列創建索引,那么列Age和Address上的值並不會存儲在這個索引當中。如果我們確實把其他所有字段也存儲在個這個索引中,那就成了拷貝一整張表做為索引-這樣會占用太大的空間而且會十分低效。同時存儲了指向表中的相應行的指針。指針是指一塊內存區域, 該內存區域記錄的是對硬盤上記錄的相應行的數據的引用。

  4、何時使用索引

   數據庫什么時候使用索引 - 數據庫自己決定,當這個SQL (SELECT * FROM Employee WHERE Name = "Jesus" )運行時,數據庫會檢查在查詢的列上是否有索引。假設Employee_Name列上確實創建了索引,數據庫會接着檢查使用這個索引做查詢是否合理,若合理則使用索引.

   索引不應該用於小規模的表,當字段用於WHERE子句作為過濾器會返回表里的大部分記錄時,該字段就不適合設置索引。經常被操作的字段不應該設置索引,因為對索引的維護會變得很繁重。

(2)什么樣的數據結構可以作為MySQL索引:B+樹和哈希表

  1、B+樹索引

   B+樹是最常用的用於索引的數據結構。因為它們是時間復雜度低, 查找、刪除、插入操作都可以可以在對數時間內完成。另外一個重要原因存儲在B+樹中的數據是有序的

  2、數據庫索引為什么用B+樹而不用AVL、紅黑樹

   雖說AVL 樹和紅黑樹這些二叉樹結構的數據結構可以達到最高的查詢效率,AVL樹和紅黑樹常用於存儲內存中的有序數據,增刪很快.在大規模數據存儲的時候,紅黑樹往往出現由於樹的深度過大而造成磁盤IO讀寫過於頻繁,進而導致效率低下的情況。B+樹只有葉節點存放數據,其余節點用來索引,而B-樹是每個索引節點都會有Data域。所以從Mysql(Inoodb)的角度來看,B+樹是用來充當索引的,一般來說索引非常大,尤其是關系性數據庫這種數據量大的索引能達到億級別,所以為了減少內存的占用,索引也會被存儲在磁盤上。 Mysql通過磁盤IO次數衡量查詢效率.B-樹/B+樹 的特點就是每層節點數目非常多,層數很少,目的就是為了就少磁盤IO次數,但是B-樹的每個節點都有data域(指針),這無疑增大了節點大小,說白了增加了磁盤IO次數(磁盤IO一次讀出的數據量大小是固定的,單個數據變大,每次讀出的就少,IO次數增多,一次IO多耗時),而B+樹除了葉子節點其它節點並不存儲數據,節點小,磁盤IO次數就少. B+樹所有的Data域在葉子節點,一般來說都會進行一個優化,就是將所有的葉子節點用指針串起來。這樣遍歷葉子節點就能獲得全部數據,這樣就能進行區間訪問.據磁盤查找存取的次數往往由樹的高度所決定,所以,只要我們通過某種較好的樹結構減少樹的結構盡量減少樹的高度,B樹可以有多個子女,從幾十到上千,可以降低樹的高度。

  3、哈希索引

   使用哈希索引的原因是,在尋找值時哈希表效率極高。所以,如果使用哈希索引,對於比較字符串是否相等的查詢能夠極快的檢索出的值。例如之前我們討論過的這個查詢(SELECT * FROM Employee WHERE Employee_Name = ‘Jesus’) 就可以受益於創建在Employee_Name 列上的哈希索引。哈系索引的工作方式是將列的值作為索引的鍵值(key),和鍵值相對應實際的值(value)是指向該表中相應行的指針。因為哈希表基本上可以看作是關聯數組,一個典型的數據項就像“Jesus => 0x28939″,而0x28939是對內存中表中包含Jesus這一行的引用。在哈系索引的中查詢一個像“Jesus”這樣的值,並得到對應行的在內存中的引用,明顯要比掃描全表獲得值為“Jesus”的行的方式快很多。缺點是哈希表是無順的數據結構,只適合查詢鍵值對-也就是說查詢相等的查詢不適合比較大小的查詢語句中.

(3)索引的特征:索引有兩個特征,即唯一性索引和復合索引。

  1、唯一性索引保證索引列不包含重復數據,不會包含冗余數據;可以使用多個列,但是必須確保索引列中每個值組合都是唯一的。如果表中已經有一個主鍵約束或者唯一性鍵(可以是多個列)約束,那么當創建表或者修改表時,SQL Server自動創建一個唯一性索引。然而,如果必須保證唯一性,那么應該創建主鍵約束或者唯一性鍵約束,而不是創建一個唯一性索引。當創建唯一性索引 時,應該認真考慮這些規則:當在表中創建主鍵約束或者唯一性鍵約束時,SQL Server自動創建一個唯一性索引;如果表中已經包含有數據,那么當創建索引時,SQL Server檢查表中已有數據的冗余性;每當使用插入語句插入數據或者使用修改語句修改數據時,SQL Server檢查數據的冗余性:如果有冗余值,那么SQL Server取消該語句的執行,並且返回一個錯誤消息;確保表中的每一行數據都有一個唯一值,這樣可以確保每一個實體都可以唯一確認;只能在可以保證實體 完整性的列上創建唯一性索引,例如,不能在人事表中的姓名列上創建唯一性索引,因為人們可以有相同的姓名。

  2、復合索引就是一個索引創建在兩個列或者多個列上。在搜索時,當兩個或者多個列作為一個關鍵值時,最好在這些列上創建復合索引。復合列的長度不能太長;在復合索引中,所 有的列必須來自同一個表中,不能跨表建立復合列;在復合索引中,列的排列順序是非常重要的,因此要認真排列列的順序,原則上,應該首先定義最唯一的列,例 如在(COL1,COL2)上的索引與在(COL2,COL1)上的索引是不相同的,因為兩個索引的列的順序不同.

  3、聚集索引和非聚集索引:

   1)聚集索引:在葉節點存放一整行記錄的索引被稱為聚簇索引,一個表中只能擁有一個聚集索引。

   2)非聚集索引:在葉節點存放一整行記錄的索引被稱為聚簇索引,其它稱為非聚集索引,一個表中可以擁有多個非聚集索引。

   區別:索引的葉子節點就是對應的數據節點,聚集索引的速度往往會更快,非聚集索引葉節點仍然是索引節點,只是有一個指針指向對應的數據塊,如果使用非聚集索引查詢,若查詢列中包含了其他列,而該索引沒有覆蓋的列,那么他還要回表進行二次查詢,查詢節點上對應的數據行的數據。

   非聚集索引在查詢的時候可以的話就避免二次查詢,這樣性能會大幅提升:建立兩列以上的索引,即可查詢復合索引里的列的數據而不需要進行回表二次查詢

  4、索引(復合索引)的最左匹配原則:最左優先,以最左邊的為起點任何連續的索引都能匹配上,但是遇到范圍查詢(>、<、between、like)就會停止匹配。

   1)索引可以簡單如一個列 (a),也可以復雜如多個列 (a,b,c,d),即復合索引。

   2)如果是聯合索引,那么key也由多個列組成,同時,索引只能用於查找key是否存在(相等),遇到范圍查詢(>、<、between、like左匹配)等就不能進一步匹配了,后續退化為線性查找。

   3)列的排列順序決定了可命中索引的列數

  例如:如有索引 (a,b,c,d),查詢條件 a=1 and b=2 and c>3 and d=4,則會在每個節點依次命中a、b、c,無法命中d。(c已經是范圍查詢了,d肯定是排不了序了)

(4)索引的優缺點

  1、使用索引的優點:

   1)可以大大加快 數據的檢索速度,這也是創建索引的最主要的原因。

   2)可以加速表和表之間的連接

   3)在使用分組和排序 子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。

   4)通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

  2、使用索引的缺點:

   1)索引會占用空間 - 你的表越大,索引占用的空間越大

   2)性能損失(主要值更新操作)當你在表中添加、刪除或者更新行數據的時候, 在索引中也會有相同的操作。記住:建立在某列(或多列)索引需要保存該列最新的數據。

  3、主鍵和唯一索引的區別:

   1)主鍵是一種約束,唯一索引是一種索引,兩者在本質上是不同的。

   2)主鍵創建后一定包含一個唯一性索引,唯一性索引並不一定就是主鍵。

   3)唯一性索引列允許空值,而主鍵列不允許為空值。

   4)一個表最多只能創建一個主鍵,但可以創建多個唯一索引。

  4、Hash索引的優缺點:

   優點:

    采用一定的哈希算法,把鍵值換算成新的哈希值,檢索時不需要像B+樹那樣從根節點到葉子節點逐級查找,只需一次哈希算法即可立刻定位到相應的位置,速度非常快。

   缺點:

    1)哈希索引也沒辦法利用索引完成排序

    2)不支持最左匹配原則

    3)在有大量重復鍵值情況下,哈希索引的效率也是極低的---->哈希碰撞問題。

    4)不支持范圍查詢

三、事務:

(1)事務的四個特性

  1、原子性(Atomic):事務包含的所有操作要么全部成功,要么全部失敗回滾;成功必須要完全應用到數據庫,失敗則不能對數據庫產生影響;

  2、一致性(Consistency)事務執行前和執行后必須處於一致性狀態,例:用戶A和用戶B的前加起來一共是5000; 無論AB用戶之間是如何相互轉換的,事務結束后兩個用戶的錢加起來還是5000,這就是事務的一致性。

  3、隔離性(Isolation):當多個用戶並發訪問數據庫時,數據庫為每一個用戶開啟的事務,不被其他事務的操作所干擾,多個並發事務之間要相互隔離;

  4、持久性(Durability):一個事務一旦被提交了,那么對數據庫中的數據的改變就是永久性的

(2)事務的隔離級別:

  隔離性:當多個線程都開啟事務來操作數據庫中的數據時,數據庫系統要進行隔離操作,以保證各個線程獲取數據的准確性。 不考慮事務的隔離性,會產生的幾種問題:

  1、臟讀:是指一個事務處理過程里讀取了另一個未提交的事務中的數據,然后使用了這個數據;

  2、不可重復讀:在一個事務內,多次讀取同一個數據,在這個事務還沒有結束 ,另一個事務也訪問該同一數據,但是由於第二個事務的修改,那么第一個事務兩次讀取的數據可能不一樣,因此稱為不可重復讀

  3、幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這好像發生了幻覺一樣,這就叫幻讀。

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

  隔離級別:

  1、Read uncommitted(讀未提交):最低級別,任何情況都會發生。級別最低,執行效率最高,讀取未提交的數據被稱為臟讀。

  2、Read Committed(讀已提交):可避免臟讀的發生。

  3、Repeatable read(可重復讀):可避免臟讀、不可重復讀的發生。Mysql的默認級別,級別最高,執行效率最低

  4、Serializable(串行化):避免臟讀、不可重復讀,幻讀的發生。

(3)就前三種隔離級別進行場景設計:

01: Read uncommitted 讀未提交; 公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而singo正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速回滾了事務,修改金額后,將事務提交,最后singo實際的工資只有2000元,singo空歡喜一場。

02:Read committed 讀已提交; singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,為何......

03:Repeatable read 重復讀 當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。

四、數據庫的4中引擎:

(1)MyISAM存儲引擎:節點的data域存儲的是數據地址,索引是索引,數據是數據。

 

(2)innoDB:data域存的是數據本身,索引也是數據。

 

(3)MyISAM與InnoDB的區別:

  1、MyISAM不支持事務,是非事務安全的,而InnoDB具有提交、回滾和崩潰恢復能力的事務安全

  2、MyISAM鎖的粒度是表級的,不支持外鍵,而InnoDB支持行級鎖,支持外鍵。

  3、MyISAM管理非事務表,提供高速搜索能力,如果在應用中執行大量select操作可選擇

  4、InnoDB用於事務處理,具有ACID事務支持等特性,如果在應用中執行大量insert和update操作,可選擇。

  5、支持3種不同的存儲格式,分別是:靜態表(表中的字段都是非變長字段,這樣每個記錄都是固定長度的,優點存儲非常迅速,容易緩存,出現故障容易恢復;缺點是占用的空間通常比動態表多);動態表(記錄不是固定長度的,這樣存儲的優點是占用的空間相對較少;缺點:頻繁的更新、刪除數據容易產生碎片,需要定期執行optimize table);壓縮表(因為每個記錄是被單獨壓縮的,所以只有非常小的訪問開支)

(4)Memory存儲引擎:Memory存儲引擎使用存在於內存中的內容來創建表。每個memory表只實際對應一個磁盤文件,memory類型的表訪問非常的快,默認使用HASH索引,但是一旦服務關閉,表中的數據就會丟失掉。

(5)Merge存儲引擎:Merge存儲引擎是一組MyISAM表的組合,這些MyISAM表必須結構完全相同,merge表本身並沒有數據,對merge類型的表可以進行查詢,更新,刪除操作,這些操作實際上是對內部的MyISAM表進行的。

五、Mysql的查詢優化:

 Mysql是如何執行查詢的:

  (1)客戶端發送一條查詢給服務器;

  (2)服務器先檢查查詢緩存,如果命中了緩存,則立刻返回存儲在緩存中的結果。否則進入下一階段;

  (3)服務器進行SQL解析、預處理、在由查詢優化器生成對應的執行計划;

  (4)MySQL根據優化器生成的執行計划,調用存儲引擎的API來執行查詢。

  (5)將結果返回給客服端,同時也會放入查詢緩存中。

 如下圖所示:

  

 六、SQL的優化

 驅動表:指定了聯接條件時,滿足查詢條件的記錄行數少的表為[驅動表]

     未指定聯接條件時,行數少的表為[驅動表](Important!)

 永遠用小結果集驅動大結果集(Important)

  優化查詢:

  (1)重新定義關聯表的順序;小表放在前面,大表放在后面.

  (2)將外連接轉化為內連接

  (3)優化器主要根據定義的索引來提高性能,可以設置索引, 避免在索引列上使用IS NULL和IS NOT NULL

  (4) 用IN來替換OR 

  (5)避免SELECT *,因為它會進行全表掃描,不能有效利用索引

  (6)分組group by 優化,默認情況下group by 對字段分組的時候,會排序

  (7)order by的列盡量索引.使用limit來實現分頁邏輯.

  (8)比較運算符能用 “=”就不用“<>”,“=”增加了索引的使用幾率


免責聲明!

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



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