1. 程式人生 > 其它 >mysql索引基本原理

mysql索引基本原理

mysql整體架構:client層——>server層——>儲存引擎
  • client向server層傳送SQL語句,server層通過聯結器接收
  • server層的分析器對SQL語句進行語法分析,轉變為AST抽象語法樹
  • server層使用優化器對語句中具體查詢的資料
    • RBO:基於規則的優化
    • CBO:基於成本優化
  • 執行器與儲存引擎進行IO互動,獲取查詢結果
資料儲存在磁碟,一般情況況下查詢速率慢,都是卡在IO上。因此需要在滿足需求的前提下提高IO效率:
  • 減少IO次數
  • 減少IO量
一些概念
  • 區域性性原理:資料和程式都有聚整合群的傾向,同事之前訪問過的資料很可能再次查詢。
  • 磁碟預讀:記憶體跟磁碟在發生資料互動的時候,一般情況下有一個最小的邏輯單元,即"
    "/"datapage",頁一般由作業系統決定是多大,一般是4k或8k。而進行資料互動的時候,可以取頁的整數倍來讀取。如innodb引擎每次讀取資料都是16k
  • OLAP與OLTP
    • OLAP:聯機分析處理:對海量歷史資料進行分析,產生決策性的影響(資料倉庫——Hive等)
    • OLTP:聯機事務處理:要求在很短的時效內返回對應的結果(資料庫——關係型資料庫)
  • B+樹
    • 每個關鍵字對應一棵子樹
    • 每個結點關鍵字個數n的範圍是[m/2]<=n<=m
    • 葉節點是包含資訊的,其他所有非葉節點僅起到索引作用,包含了對應子樹的最大關鍵字和指向該子樹的指標
儲存本身是儲存在磁碟的,查詢資料時優先將索引載入在記憶體。索引儲存的資訊是這種key-value型別的資料:
  • key:唯一標識,也就是實際資料行中儲存的值
  • 檔案地址(offset):偏移量
  • Mysql索引系統的資料結構採用3~4層的B+樹,這個層數是由具體磁碟計算出來的。3~4層的B+樹就可以存放千萬級的資料,如果還需存放則需要擴容加表。
  • B+樹的最底層即葉子節點是所有的資料,它形成了一個雙向連結串列,用於對主鍵的範圍查詢和分頁查詢。因此B+樹有兩種查詢運算,還有一種就是正常的從根節點隨機查詢
  • 在一個磁碟塊中,指標大小是固定的,因此當選擇某欄位當索引時,應該儘量減小鍵值所佔用的空間,這樣可以指數級地增加用於存放資料的空間
當索引使用不同資料結構:
  • hash:雜湊衝突;範圍查詢時需逐個遍歷;對於記憶體空間要求高。mysql中也存在hash,即memory引擎使用的是hash索引,innodb支援自適應hash,即系統根據資料型別判斷使用哪種儲存結構
    • 二叉樹:無序
    • BST:二叉查詢樹:插入時有序,左子樹小於子樹根節點,右子樹大於子樹根節點
      • 插入連續值時,可能退化成連結串列,時間複雜度提高
    • AVL:平衡二叉查詢樹:有序,為了解決連續值退化的問題,通過左旋或右旋讓樹平衡,保持最短子樹和最長子樹高度不能超過1
      • 通過插入效能的損失來彌補查詢效能的提升
    • 紅黑樹:在旋轉平衡的基礎上,新增變色的行為。保持最長子樹不超過最短子樹的2倍即可。使得查詢效能和插入效能近似一致
  • 隨著資料的插入,樹的深度越來越深,意味著IO次數越多,影響資料讀取的效率,因此使用開始使用樹
    • B樹:多岔樹,有序,非葉子節點也是儲存著資料的,佔用空間較大
    • B+樹:多岔樹,有序,只有葉子節點儲存著資料,非葉子節點儲存的是指標
索引的建立跟儲存引擎是掛鉤的,儲存引擎表示不同資料在磁碟的不同組織形式 在windows上的Mysql中,檔案都是以不同字尾併成對的形式存在。資料結構用的都是B+樹,而儲存形式又有所不同
  • .frm:存放表結構
  • .MYD和.MYI:引擎是myisam,非聚簇索引。
    • .MYD:資料,Data
    • .MYI:索引,index
  • .ibd:儲存資料+索引,即引擎是innodb。只能有一個聚簇索引,可以有很多非聚簇索引。在插入資料時,必須要包含一個索引的key值。這個索引的key值可以是主鍵;若沒有主鍵也可以是唯一鍵;若唯一鍵也沒有,就會有一個自生成的6位元組的rowid(對使用者不可見)
——聚簇索引與非聚簇索引——二者取決於資料和索引是否是放在一起的 ——mysql表中有且至少有一個索引 一些概念2.0: 回表:假設表中有一個聚簇索引和一個非聚簇索引,當查詢整行記錄時,通過非聚簇索引查詢到主鍵id(即聚簇索引),再根據id查詢到整行的記錄。這種現象叫做回表,回表走了2次B+樹
  • 定義:根據普通索引查詢到聚簇索引的key值之後,再根據key值在聚簇索引中獲取所有行記錄
索引覆蓋:若查詢結果包含普通索引列和聚簇索引列,則會直接返回,不需要從聚簇索引查詢任何資料,這就叫索引覆蓋
  • 注:面試常問——在設定主鍵時是否需要自增?答:在滿足業務需求的情況下,能自增儘量自增。因為自增是累加的,對前面的資料沒有影響,無需做插入操作,也就無需做磁碟塊/頁分裂的操作(當在一頁資料裡插入資料時,如果資料滿了就需要分裂成多個頁或者磁碟塊來儲存,父親節點也可能需要分裂,而分裂會影響效率)。追加的效率較高
最左匹配:組合索引的匹配規則。若一張表裡有兩列是組合索引,那麼使用時必須先匹配左側的列,再匹配右側列
  • select * fro table where name=? and age=? 允許使用
  • select * fro table where name=? 允許使用
  • select * fro table where age=? 無法使用
  • select * fro table where age=? and name=? 允許使用
  • 只要查詢條件是組合索引,那麼就算順序相反,mysql內部的優化器會調整對應的順序
索引下推(mysql5.7後特性):使用組合索引時,直接根據組合索引在儲存引擎中獲取對應資料,無需在server層二次過濾(5.7之前),減少了server層於儲存引擎的互動,減少了IO量,提高了效率 profiling——mysql自帶的效能分析工具(單條語句)
  • 開啟profiling:set profiling=1;
  • 執行SQL語句,然後show profiles; 即可查出上條語句執行的實際時間
  • 想要查詢profiles結果表中具體某條語句的所有狀態耗費時長,或者想查詢某條語句的某個狀態的使用情況,根據可使用profiles表語句對應的Query_ID來查詢,語法如下:show profile for [type] query [id]。但這種查詢方式在未來版本可能會被其他工具所取代
進階--Myysql效能模式: 5.7預設開啟效能模式,在初始資料庫中,會有一個performance_schema庫,裡面有眾多相關表,而通過show variables like 'performance_schema';查詢效能模式的開啟狀態。而修改狀態無法直接update,需要更改mysql配置檔案my.cnf https://www.bilibili.com/video/BV1ov41137Vo?p=10