1. 程式人生 > 實用技巧 >部落格樣式(未更新完)

部落格樣式(未更新完)

sql優化

一.定位問題

1.show profiles的使用

  • show profileshow profiles 語句可以展示當前會話(退出 session 後, profiling 重置為0) 中執行語句的資源使用情況.
  • Profiling 功能由MySQL會話變數 : profiling 控制,預設是OFF.關閉狀態.

1.1 確定資料庫版本

Select  version();

Show profiles5.0.37之後新增的,要想使用此功能,要確保版本在5.0.37之後。

1.2 確定是否開啟 profiles 功能

SHOW VARIABLES LIKE 'profiling';
#或
select @@profiling;

如果off

set profiling=ON;
#或
set profiling=1;

1.3執行要查詢的sql

SELECT COUNT(id) FROM student;

1.4 執行 show profiles 檢視分析列表

show profiles;

show profiles 顯示最近發給伺服器的多條語句,條數根據會話變數 profiling_history_size 定義,預設是15,最大值為100。由query_idduration 以及query組成

1.5 執行 show profile

show profile all for query query_id;
  • 根據query_id 檢視某個查詢的詳細時間耗費
  • all可替換
    • ALL:顯示所有開銷資訊
    • BLOCK IO:阻塞的輸入輸出次數
    • CONTEXT SWITCHES:上下文切換相關開銷資訊
    • CPU:顯示CPU的相關開銷資訊
    • IPC:接收和傳送訊息的相關開銷資訊.
    • MEMORY :顯示記憶體相關的開銷,目前無用
    • PAGE FAULTS :顯示頁面錯誤相關開銷資訊
    • SOURCE :列出相應操作對應的函式名及其在原始碼中的呼叫位置(行數)
    • SWAPS:顯示swap交換次數的相關開銷資訊

2. explain 的使用

根據 show profiles 的使用,問題 Sending data時間過長. Sending data

狀態包含 ( 收集 資料->傳送 資料),懷疑沒有走索引

explain SELECT COUNT(id) FROM student;

使用只需要在執行語句前新增 explain即可

expain出來的資訊有10列,分別是

  1. id:選擇識別符號
  2. select_type:表示查詢的型別。
  3. table:輸出結果集的表
  4. partitions:匹配的分割槽
  5. type:表示表的連線型別
  6. possible_keys:表示查詢時,可能使用的索引
  7. key:表示實際使用的索引
  8. key_len:索引欄位的長度
  9. ref:列與索引的比較
  10. rows:掃描出的行數(估算的行數)
  11. filtered:按表條件過濾的行百分比
  12. Extra:執行情況的描述和說明

2.1 id、

select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序

  • id相同
    • 執行順序由上至下
  • id不同
    • id值越大,執行優先順序越高
    • 如果行引用其他行的並集結果,則該值可以為NULL
  • id相同不同,同時存在
    • 可以認為相同id為一組,同組從上往下順序執行
    • 所有組,id值越大,優先順序越高,越先執行

2.2 select_type

  1. **simple:** 簡單的select查詢,沒有union或者子查詢
  2. primary: 最外層的select查詢
  3. union: union中的第二個或隨後的select查詢,不依賴於外部查詢的結果集
  4. dependent union: union中的第二個或隨後的select查詢,依賴於外部查詢的結果集
  5. subquery: 子查詢中的第一個select查詢,不依賴與外部查詢的結果集
  6. dependent subquery: 子查詢中的第一個select查詢,依賴於外部查詢的結果集
  7. derived: 用於from子句中有子查詢的情況,mysql會遞迴執行這些子查詢,此結果集放在臨時表中

3、table

table用來表示輸出行所引用的表名

4、type(重要)

null > system > const > eq_ref > ref > range > index > all

  1. NULL: MySQL在優化過程中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裡選取最小值可以通過單獨索引查詢完成。
  2. system 表只有一行記錄(等於系統表),這是const型別的特列,平時不會出現,這個也可以忽略不計
  3. const 表示通過索引一次就找到了,const用於比較primary key 或者unique索引。因為只匹配一行資料,所以很快。如將主鍵置於where列表中,MySQL就能將該查詢轉換為一個常量。
explain
SELECT id
FROM teacher
WHERE id =
      (SELECT teacher_id
       FROM student
       WHERE student.id = 1 );

這裡type 都是const

  1. eq_ref 唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描
  2. ref 非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以他應該屬於查詢和掃描的混合體。
  3. range 只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引,一般就是在你的where語句中出現between、< 、>、in等的查詢,這種範圍掃描索引比全表掃描要好,因為它只需要開始於索引的某一點,而結束於另一點,不用掃描全部索引。
  4. index Full Index Scan,Index與All區別為index型別只遍歷索引樹。這通常比ALL快,因為索引檔案通常比資料檔案小。(也就是說雖然all和Index都是讀全表,但index是從索引中讀取的,而all是從硬碟讀取的)
  5. all Full Table Scan 將遍歷全表以找到匹配的行

2.5 possible_keys

possible_keys 顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一定被查詢實際使用

該列完全獨立於EXPLAIN輸出所示的表的次序。這意味著在 possible_keys 中的某些鍵實際上不能按生成的表次序使用。
如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢效能。如果是這樣,創造一個適當的索引並且再次用EXPLAIN檢查查詢

2.6 key

key 列顯示的是當前表實際使用的索引,如果沒有選擇索引,則此列為null,要想強制MySQL使用或忽視possible_keys 列中的索引,在查詢中使用FORCE INDEXUSE INDEX 或者 IGNORE INDEX

2.7 key_len

  • 表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下 ,長度越短越好key_len 顯示的值為索引欄位的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的。

  • key len的長度還和字符集有關,latin1一個字元佔用1個位元組,gbk一個字元佔用2個位元組,utf8一個字元佔用3個位元組。key_len的計演算法方法:

    • 列型別 KEY_LEN 備註
      id int key_len = 4+1 int為4bytes,允許為NULL,加1byte
      id bigint not null key_len=8 bigint為8bytes
      user char(30) utf8 key_len=30*3+1 utf8每個字元為3bytes,允許為NULL,加1byte
      user varchar(30) not null utf8 key_len=30*3+2 utf8每個字元為3bytes,變長資料型別,加2bytes
      user varchar(30) utf8 key_len=30*3+2+1 utf8每個字元為3bytes,允許為NULL,加1byte,變長資料型別,加2bytes
      detail text(10) utf8 key_len=30*3+2+1 TEXT擷取部分,被視為動態列型別。

2.8 ref

ref 列用來顯示使用哪個列或常數與key一起從表中選擇相應的行。它顯示的列的名字(或const),此列多數時候為null

2.8 rows

rows列顯示的是mysql解析器認為執行此SQL時必須掃描的行數。此數值為一個預估值,不是具體值,通常比實際值小,也就是說,用的越少越好

2.9 filtered

此引數為mysql 5.7 新加引數,指的是返回結果的行數所佔需要讀到的行(rows的值)的比例 . 對於使用join時,前一個表的結果集大小直接影響了迴圈的行數

Filtered 表示返回結果的行數佔需讀取行數的百分比 Filtered 列的值越大越好 Filtered列的值依賴於統計資訊

2.10 extra(重要)

包含不適合在其他列中顯式但十分重要的額外資訊

  1. using index: 該值表示這個SQL語句使用了覆蓋索引(覆蓋索引是指可以直接在索引列中得到想要的結果,而不用去回表),此時效率最高

如果同時出現using where,表明索引被用來執行索引鍵值的查詢;如果沒有同時出現using where,表明索引用來讀取資料而非執行查詢動作。

  1. using where: 表示儲存引擎搜到記錄後進行了後過濾(POST-FILTER),如果查詢未能使用索引,using where的作用只是提醒我們mysql要用where條件過濾結果集
  2. using temporary 表示mysql需要使用臨時表來儲存結果集,常見於排序和分組查詢
  3. using filesort: 是指mysql無法利用索引直接完成排序(排序的欄位不是索引欄位),此時會用到緩衝空間來進行排序

說明mysql會對資料使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。MySQL中無法利用索引完成的排序操作稱為“檔案排序”。

  1. using join buffer: 強調在獲取連線條件時沒有用到索引,並且需要連線緩衝區來儲存中間結果。(效能可以通過新增索引或者修改連線欄位改進) Block Nested Loop是指Block Nested-Loop Join演算法:將外層迴圈的行/結果集存入join buffer, 內層迴圈的每一行與整個buffer中的記錄做比較,從而減少內層迴圈的次數.

  2. impossible where: 表示where條件導致沒有返回的行

  3. using index condition: 是mysql 5.6 之後新加的特性,結合mysql的ICP(Index Condition Pushdown)特性使用。主要是優化了可以在索引(僅限二級索引)上進行 like 查詢

    如果extra中出現多個上面結果,則表示順序使用上面的方法進行解析查詢

  4. distinct 優化distinct操作,在找到第一匹配的元組後即停止找同樣值的動作

二.問題解決

我這裡是因為沒有新增索引,所以新增索引就完事了

CREATE INDEX index_name ON table_name ( 要新增索引的列名 );

索引的影響

優點

  • 可以大大加快資料的檢索速度,這也是建立索引的最主要的原因。
  • 可以加速表和表之間的連線,特別是在實現資料的參考完整性方面特別有意義。
  • 在使用分組和排序子句進行資料檢索時,同樣可以顯著減少查詢中分組和排序的時間。
  • 通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的效能。

缺點

  • 建立索引和維護索引要耗費時間,這種時間隨著資料量的增加而增加。
  • 索引需要佔物理空間,除了資料表佔資料空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大。
  • 當對錶中的資料進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了資料的維護速度。

添加註意

  • 對於那些在查詢中很少使用或者參考的列不應該建立索引。

    這是因為,既然這些列很少使用到,因此有索引或者無索引,並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度和增大了空間需求。

  • 對於那些只有很少資料值的列也不應該增加索引。

    這是因為,由於這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的資料行佔了表中資料行的很大比例,即需要在表中搜索的資料行的比例很大。增加索引,並不能明顯加快檢索速度。

  • 對於那些定義為text, image和bit資料型別的列不應該增加索引。

    這是因為,這些列的資料量要麼相當大,要麼取值很少。

  • 當修改效能遠遠大於檢索效能時,不應該建立索引。

    這是因為,修改效能和檢索效能是互相矛盾的。當增加索引時,會提高檢索效能,但是會降低修改效能。當減少索引時,會提高修改效能,降低檢索效能。因此,當修改效能遠遠大於檢索效能時,不應該建立索引。

1、表的主鍵、外來鍵必須有索引;
2、資料量超過300的表應該有索引;
3、經常與其他表進行連線的表,在連線欄位上應該建立索引;
4、經常出現在Where子句中的欄位,特別是大表的欄位,應該建立索引;
5、索引應該建在選擇性高的欄位上;
6、索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不要建索引;
7、複合索引的建立需要進行仔細分析;儘量考慮用單欄位索引代替:
A、正確選擇複合索引中的主列欄位,一般是選擇性較好的欄位;
B、複合索引的幾個欄位是否經常同時以AND方式出現在Where子句中?單欄位查詢是否極少甚至沒有?如果是,則可以建立複合索引;否則考慮單欄位索引;
C、如果複合索引中包含的欄位經常單獨出現在Where子句中,則分解為多個單欄位索引;
D、如果複合索引所包含的欄位超過3個,那麼仔細考慮其必要性,考慮減少複合的欄位;
E、如果既有單欄位索引,又有這幾個欄位上的複合索引,一般可以刪除複合索引;
8、頻繁進行資料操作的表,不要建立太多的索引;
9、刪除無用的索引,避免對執行計劃造成負面影響;

酌情參考

參考網址

explain

https://blog.csdn.net/why15732625998/article/details/80388236

https://www.cnblogs.com/37Y37/p/11489881.html

force index()使用

https://www.bbsmax.com/A/kPzO2M2wdx/

https://www.cnblogs.com/-mrl/p/13088609.html

profile/show profiles

https://blog.csdn.net/zxc_user/article/details/78645997

https://blog.csdn.net/qq_38852289/article/details/77741898

sending data狀態包含了什麼

https://blog.csdn.net/qq_40963977/article/details/106856877

新增索引

https://www.cnblogs.com/jpfss/p/9155542.html