【數據庫】-- MySQL SQL調優筆記(1)

1.索引

1.1.定義

MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構

我們平常所說的索引,如何沒有特別的指明,都是B樹(多路搜索樹,並不一定是二叉的)結構組織索引,其中聚集索引,次要索引,覆蓋索引,複合索引,前綴索引,唯一索引默認都是使用B+樹索引,統稱索引,當然除了B+數這種類型的索引外還有(hash索引等)

1.2.優劣勢

索引

優勢

類似大學圖書館建書目索引,提高數據檢索的效率,降低數據IO成本

通過索引列對數據排序,降低數據排序的成本,降低CPU的消耗

劣勢

實際上索引也是一張表,該表保存了主鍵和索引字段,並指向實體表的記錄,所以索引也是要佔空間的

雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅 要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整因爲更新所帶來的鍵值變化後的索引信息

索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢

1.3.索引分類

單值索引:一個索引只包含單個列,一個表可以有多個單列索引

唯一索引:索引列的值必須唯一,但允許有空值

複合索引:一個索引包含多個列

基本語法:

創建:

CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length))
ALTER mytable add[unique] index [indexname] on (columnname(length))

刪除:

DROP INDEX[INDEXNAME] ON Mytable

查看:

show index from table_name\G

使用ALTER命令:

ALTER TABLE tbl_name ADD PRIMARY KEY (column_list) #該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能爲NULL

ALTER TABLE tbl_name ADD UNIQUE index_name (column_list) #這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)

ALTER TABLE tbl_name ADD INDEX index_name (column_list)  #添加普通索引,索引值可出現多次

ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list) #該語句指定了索引爲FULLTEXT,用於全文索引

1.4.索引使用場景

哪些情況需要創建索引:

1.主鍵自動建立唯一索引;

2.頻繁作爲查詢條件的字段應該創建索引;

3.查詢中與其它表關聯的字段,外鍵關係建立索引;

4.頻繁更新的字段不適合創建索引-因爲每次更新不單單是更新了記錄還會更新索引;

5. Where條件裏用不到的字段不創建索引;

6.單鍵/組合索引的選擇問題,who? (在高併發下傾向創建組合索引);

7.查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度;

8.查詢中統計或者分組字段

哪些情況不要創建索引:

1.表記錄太少;

2.經常增刪改的表;

3.數據重複且分佈平均的表字段,因此應該只爲最經常查詢和最經常排序的數據列建立索引。

注意,如果某個數據列包含許多重複的內容,爲它建立索引就沒有太大的實際效果。

2.Explain性能分析

使用Explain關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句,分析你的查詢語句或是表結構的性能瓶頸。

具體分析結果包含:表的讀取順序數據的讀取操作的操作類型哪些索引可以使用哪些索引被實際使用表之間的引用每張表有多少行被優化器查詢

2.1.id(執行順序)

explain + sql 執行之後會顯示如下信息列,表示mysql執行當前sql的執行信息。

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

id顯示的執行順序一共有三種情況:

①id相同,執行順序由上至下;

②id不同,如果是子查詢,id序號會遞增,id值越大優先級越高,越優先被執行

③id相同與不同,同時存在

 

2.2.select_type(查詢類型)

select_type:表示查詢的類型,主要是用於區別該條sql語句是普通查詢聯合查詢子查詢等的複雜查詢

select_type的類型有以下幾種:

 SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union;

 PRIMARY:查詢中若包含任何複雜的子部分,最外層則被標記爲;

 SUBQUERY:在select或where列表中包含子查詢;

 DERIVED:在FROM列表中包含子查詢被標記爲DERIVED (衍生) MYSQL會遞歸執行這些子查詢,把結果放在臨時表中

 UNION:若第二個SELECT出現在UNION之後,則被標記爲UNION,若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲DERIVED

 UNION RESULT:從UNION表獲取結果的SELECT

2.3.Table

table用於顯示這一行數據是來自哪一張表的

2.4.Type

type顯示的是訪問類型,是較爲重要的一個指標,主要的類型有:

 一般在實際開發中,結果值從最好到最壞依次是:

system > const > eq_ref > ref > range > index > ALL

一般來說,sql優化得保證查詢至少達到range級別,最好能達到ref。

 

system:表中只有一行記錄(等於系統表),這是const類型的特例,平時不會出現,這個也可以忽略不計;

const:表示通過索引一次就找到了,const用於比較primary key 或者unique索引,因爲只匹配一行數據,所以很快將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量

eq_ref:唯一索引掃描,對每個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或唯一索引掃描

ref:非唯一性索引掃描,返回匹配的某個單獨值所有行,本質上也是一種索引訪問,

它返回所有匹配單個單獨值的行,然而他可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體

range:只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引,一般就是在where語句中出現了between、<>、in等查詢,這種範圍掃描比

全表掃描要好,因爲它開始於索引的某一點而結束於另一點,不用掃描全部索引

 index:index與ALL區別爲index類型值遍歷索引,通常比ALL快,因爲索引文件通常比數據文件小

(all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)

all:全表掃描,將遍歷全表以找到匹配的行

2.5.possible_keys/key

possible_keys:顯示可能應用在這張表中的索引,一個或多個查詢設計到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

key:實際使用的索引,如果爲NULL,則沒有使用索引

注意:查詢中若使用了覆蓋索引,則該索引僅出現在key列表中

2.6.key_len

key_len:表示索引中使用的字節數,可通過該列計算查詢中使用的索引長度,在不損失精確性的情況下,長度越短越好

key_len顯示的值爲索引字段的最大可能長度,並非實際使用長度,及key_len是根據表定義計算而得,而不是通過表內檢索出的

 

 原則:同一檢索條件下,key_len長度越短越好,消耗小、性能高。

2.7.ref

ref:顯示索引的那一列被使用了,如果可能的話,是一個常數,那些列或常量被用於查找所有列上的值

 2.8.rows

rows:根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要的讀取行數

2.9.Extra

extra:包含不適合在其它列中顯示但十分重要的額外信息,主要類型有:

Using filesort:說明mysql會對數據使用一個外部索引排序,而不是按照表內的索引順序進行讀取,MySQL中無法利用索引完成的排序操作稱爲“文件排序”

Using temporary:使用臨時表保存了中間結果,MySQL在對查詢結果排序時時使用臨時表,常見於排序order by 和分組查詢group by

Using index:表示相應的select操作中使用了覆蓋索引(Covering Index) 避免訪問了表的數據行,效率不錯,如果同時出現using where 表明索引被用來執行索引鍵值的查找。如果沒有出現using where 表明該索引用來讀取數據而非執行查找動作

覆蓋索引:又名索引覆蓋,就是select的數據列只用從索引中就能獲取,不必讀取數據行,MySQL可以利用索引返回select列表中的字段,而不必根據索引再次讀取數據文件,換句話說查詢列要被所建的索引覆蓋

Using where:表示where連接

Using join buffer:表示使用了連接緩存

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章