1. 程式人生 > 其它 >網路程式設計總結

網路程式設計總結

Mysql的優化,一般是對索引優化,這裡主要以innodb為主

索引是幫助MySQL高效獲取資料的排好序的資料結構,排好序是索引資料結構的特點,也是索引優化的前提。

1. 索引資料結構

索引底層使用B+樹作為其底層儲存結構。相較於二叉樹、紅黑樹、hash表、B樹而言,B+樹有自己獨特的優勢。

B+樹特點

  • 非葉子節點不儲存data,只儲存索引(冗餘),可以放更多的索引
  • 葉子節點包含所有索引欄位
  • 葉子節點用指標連線,提高區間訪問的效能

1.1 聚集索引(主鍵索引)

聚集索引指索引包含了完整的資料記錄,一般主鍵索引是聚集索引

mysql使用B+樹儲存索引,頁大小預設為16K,mysql在查詢時會一次性將一個頁載入到記憶體中(一次磁碟I/O),在記憶體中可以快速定位下一次需要載入的頁(有一次磁碟I/O),所以一般精準查詢只需要進行三次磁碟I/O即可找到對應的資料。

1.2聯合索引

也稱非聚集索引,非聚集索引的data儲存的是聚集索引的值,如果返回的資料包含了非索引值,那麼就需要通過聚集索引找到完整的記錄,這裡就會產生回表,一般建議使用覆蓋索引,也就是查詢返回值都在索引列中,例如下圖,只返回name,age,position值的話,就不需要再去聚集索引查詢其他資料,速度會快很多。

2. 優化建議

  • 建表時儘量建主鍵(不建主鍵,mysql內部也會自己建立一個主鍵)
  • 主鍵儘量使用整型的自增主鍵(自增主鍵會減少插入)
  • 索引最佳實踐
    • 全值匹配
    • 最左字首法則
    • 不在索引列上做任何操作(計算、函式、(自動or手動)型別轉換),會導致索引失效而轉向全表掃描
    • 儲存引擎不能使用索引中範圍條件右邊的列
    • 儘量使用覆蓋索引(只訪問索引的查詢(索引列包含查詢列)),減少 select * 語句
    • mysql在使用不等於(!=或者<>),not in,not exists的時候無法使用索引會導致全表掃描<小於、>大於、<=、>=這些,mysql內部優化器會根據檢索比例、表大小等多個因素整體評估是否使用索引
    • is null,is not null 一般情況下也無法使用索引
    • like以萬用字元開頭(%abc)mysql索引失效會變成全表掃描操作
    • 字串不加單引號索引失效
    • 少用or或in,用它查詢時,mysql不一定使用索引,mysql內部優化器會根據檢索比例、表大小等多個因素整體評估是否使用索引

3. Explain

  • 模擬優化器執行SQL語句,分析你的查詢語句或是結構的效能瓶頸
  • 如果 from 中包含子查詢,仍會執行該子查詢,將結果放入臨時表中

3.1 . id列

id列的編號是 select 的序列號,有幾個 select 就有幾個id,並且id的順序是按 select 出現的順序增長的。

id列越大執行優先順序越高,id相同則從上往下執行,id為NULL最後執行

3.2 select_type列

select_type 表示對應行是簡單還是複雜的查詢

  • simple:簡單查詢。查詢不包含子查詢和union
  • primary:複雜查詢中最外層的 select
  • subquery:包含在 select 中的子查詢(不在 from 子句中)
  • derived:包含在 from 子句中的子查詢。MySQL會將結果存放在一個臨時表中,也稱為派生表
  • union:在 union 中的第二個和隨後的 select

3.3 table列

這一列表示 explain 的一行正在訪問哪個表。

當 from 子句中有子查詢時,table列是 格式,表示當前查詢依賴 id=N 的查詢,於是先執行 id=N 的查 詢。

當有 union 時,UNION RESULT 的 table 列的值為<union1,2>,1和2表示參與 union 的 select 行id

3.4 type列

關聯型別或訪問型別,即MySQL決定如何查詢表中的行

依次從最優到最差分別為:system > const > eq_ref > ref > range > index > ALL 一般來說,得保證查詢達到range級別,最好達到ref

NULL:mysql能夠在優化階段分解查詢語句,在執行階段用不著再訪問表或索引。例如:在索引列中選取最小值,可 以單獨查詢索引來完成,不需要在執行時訪問表

3.5 possible_keys列

查詢可能使用哪些索引來查詢

出現 possible_keys 有列,而 key 顯示 NULL 的情況,這種情況是因為表中資料不多,mysql認為索引 對此查詢幫助不大,選擇了全表查詢

3.6 key列

這一列顯示mysql實際採用哪個索引來優化對該表的訪問。如果沒有使用索引,則該列是 NULL。如果想強制mysql使用或忽視possible_keys列中的索引,在查詢中使用 force index、ignore index。

3.7 key_len列

顯示mysql在索引裡使用的位元組數,通過這個值可以算出具體使用了索引中的哪些列

key_len計算規則如下:

  • 字串,char(n)和varchar(n),n為字元數
    • char(n):一個數字或字母佔1個位元組,一個漢字佔3個位元組,存漢子就是3n位元組
    • 如果存漢字則長度是 3n + 2 位元組,加的2位元組用來儲存字串長度,因為 varchar是變長字串
  • 數值型別:
    • tinyint:1位元組
    • smallint:2位元組
    • int:4位元組
    • bigint:8位元組
  • 時間型別
    • date:3位元組
    • timestamp:4位元組
    • datetime:8位元組
  • 如果欄位允許為 NULL,需要1位元組記錄是否為 NULL
  • 索引最大長度是768位元組,當字串過長時,mysql會做一個類似左字首索引的處理,將前半部分的字元提取出來做索 引。

3.8 ref列

這一列顯示了在key列記錄的索引中,表查詢值所用到的列或常量,常見的有:const(常量),欄位名

3. 9rows列

是mysql估計要讀取並檢測的行數,注意這個不是結果集裡的行數

3.10 Extra列

這一列展示的是額外資訊