MySQL隨筆

尼古拉斯--铁柱發表於2024-06-07

1、隔離級別

  innoDB透過間隙鎖鎖定查詢範圍避免被其他事物修改

  未提交讀(導致髒讀)、已提交讀(導致不可重複讀)、可重複讀(mysql預設,導致幻讀)、序列化

  髒讀:事物執行的過程讀到其他事物未提交的資料  

  不可重複讀:事物a在多次讀取某資料時,事物b進行了修改,導致食物a兩次讀取結果不一樣

  幻讀:前後兩次查詢得到的結果不一樣,事物前後兩次查詢統一範圍資料時事物b進行了插入修改並提交

2、SQL最佳化

  a.增加索引;但是要避免索引失效如like、函式等

  b.避免返回不必要的資料列

  c.適當最佳化sql結構,如避免子查詢、全表掃描等

  d.分庫分表,單表資料量比較大時

  e.讀寫分離,讀多寫少時

3、索引失效情況

索引:主鍵索引、普通索引

使用ecplain 查詢sql當前執行計劃

  a 索引列上做函式運算導致失效

  b 組合索引需要按照最左匹配法則

  c 索引列存在隱式轉換時候,即索引列是字串型別但是沒有加引號

  d 索引列使用不等號或者not查詢導致失效

  e 使用like並且%加在前面時候失效,由於不符合最左匹配所以失效

  f 使用or但是語句前後沒有同時使用索引的時候也會失效

4、update執行時如果where包含索引列且只執行一個語句,使用行鎖,否則使用表鎖

5、為什麼索引不適用二叉樹而使用B+樹

二叉樹每次插入大的值需要新增到右側,深度較高,查一次就要進行一次IO,查詢效率沒有幫助。

紅黑樹也是最大的插到右側,但是會進行自旋,不會全都加到一條線,相當於平衡二叉樹,查詢次數差不多能減少一半,但是深度還是比較高,而且自旋轉也需要消耗資源。

B樹一個節點可以儲存多個元素,深度較低。

B+樹是對B樹的一個增強,如圖

innoDB引擎:自增的在新增的時候不需要修改節點,節省時間

一般推薦建立一到兩個的聯合索引(複合索引)

Explain 命令中的 type 列,顯示MySQL查詢所使用的 關聯型別(Join Types) 或者 訪問型別,它表明 MySQL決定如何查詢表中符合條件的行。
常見訪問型別效能由最差到最優依次為:

ALL < index < range < ref < eq_ref < const < system。

一般需要range級別或者達到ref級別

  range級別:

  1. 範圍條件查詢:在 WHERE 子句裡帶有 BETWEEN><>=<= 的查詢。
  2. 多個等值條件查詢:使用 IN()OR ,以及使用 like 進行字首匹配模糊查詢

非主鍵索引的都可以稱之為二級索引,二級索引是非聚集索引,沒有在葉子結點包含全部的資料,只存主鍵的id,需要根據主鍵id進行回表再查詢;

mysql5.6以後的索引下推可以減少回表

覆蓋索引查詢的欄位都在索引列中,不需要進行回表所以效率高一些。

mysql表關聯的底層實現原理:當資料量比較大的時候就算走索引也比較慢

explain關鍵引數type:

  

索引最佳化:

  • 全值匹配:使用複合索引時候,查詢條件包括索引所有的列;
  • 索引列上少算數;使用函式沒有辦法根據有序性進行檢索;
  • 範圍索引後面會失效;前面使用有序範圍後,後面的欄位是無序的;如果第一個欄位搜尋範圍小想強制使用索引可以加上關鍵字Force Index(索引名稱)防止後面欄位全表掃描
  • 儘量使用覆蓋索引,不寫星號(防止回表);explice檢視extra顯示index
  • 不等空值還有or,索引失效要少用,還有not in 、not exists也會失效,範圍查詢mysql自己判斷
  • like百分號寫右邊;
  • 單引號不要省略

sql最佳化

  • 不要寫*
  • 用小表驅動大表
  • 連線查詢代替子查詢;具體場景具體分析
  • 提升group by效率,分組欄位新增索引
  • 批次插入最佳化,mybatis提供了sqlsession.getMapper(EmpMapper.class).insertBatch(資料list),五百以內
  • 使用limit
  • union all替代union 第一個不會去重,去重時需要遍歷排序等內部操作
  • 儘量少關聯