目錄
一、索引分類
1、聚集索引
數據行的物理順序與列值(一般是主鍵的那一列)的邏輯順序相同,一個表中只能擁有一個聚集索引,數據和索引是在同一個葉子節點上的,存儲放在一起
主鍵索引:一種特殊的唯一索引,主鍵索引不允許爲空,值必須唯一;主鍵索引就是B+樹;一般建立表的同時創建主鍵索引
2、非聚集索引
該索引中索引的邏輯順序與磁盤上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引)數據和索引是在不同一個葉子節點上的,不是存儲放在一起。通過一個索引,去主鍵索引找
- 普通索引:即一個索引只包含單個列,一個表可以有多個單列索引
- 唯一索引:索引列的值必須唯一,但允許有空值(主鍵索引不允許爲空)
- 複合索引:即一個索引包含多個列index(a,b,c)
二、Mysql創建索引基本命令
查看索引 | show index from table |
創建索引 | create [unique] index index_name on mytable(columnname) |
刪除索引 | drop index indexName on mytable |
演示
創建複合索引:CREATE INDEX age_name_sex_index ON id(age,name,sex)
查看索引:SHOW INDEX FROM id
刪除索引:DROP INDEX age_name_sex_index ON id
三、執行計劃
使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸
語法:explain sql語句
執行計劃的作用
表的讀取順序、數據讀取操作的操作類型、哪些索引可以使用、哪些索引被實際使用、表之間的引用、每張表有多少行被優化器查詢
執行計劃包含信息
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
重要研究:type、key、key_len、extra
type | 訪問類型,表示找到所查詢數據的方法 |
key | 當此值存在時,說明索引生效了,但是充分利用就不知曉(是否利用了索引) |
key_len | 來計算索引是否被充分利用(是否充分用了索引) |
extra |
1、Using where說明,SQL使用了where條件過濾數據 2、Using index說明,SQL所需要返回的所有列數據均在一棵索引樹上,而無需訪問實際的行記錄 |
對type解釋的比較好的博客:https://www.jianshu.com/p/b5c01bd4a306
對extra解釋的比較好的博客:https://www.cnblogs.com/linjiqin/p/11254247.html
執行計劃之key_len字段計算分析
計算:類型(int+0,char+0,varchar+2)、長度、字符編碼、是否允許爲空(空+1 不空+0)有關
key_len=字符長度*字節數+類型+是否允許爲空
其中:char和varchar的長度是指字符數,一個字符在編碼gbk爲2個字節、utf-8爲3個字節,需要字符數*字節
例如:
name varchar(50) | 表示是varchar類型,長度爲50,允許爲空,假設是utf8編碼 | key_len=50*3+2+1=153 |
age int(255) | 表示int類型,字節數爲4,允許爲空,跟長度和編碼無關 | key_len=4+1=5 |
對於Mysql的整數類型說明補充:這裏顯示的寬度和數據類型的取值範圍是沒有任何關係的,顯示寬度只是指明Mysql最大可能顯示的數字個數,數值的位數小於指定的寬度時會由空格填充;如果插入了大於顯示寬度的值,只要該值不超過該類型的取值範圍,數值依然可以插入,而且能夠顯示出來。
演示:
EXPLAIN
SELECT age,name,sex FROM id WHERE age=2 AND name='lisi' AND sex='1'
分析:
- key值存在,說明使用了索引
- key_len=40(age=4,name=10*3+2=32,sex=1*3+1(sex是可以爲Null+1))
- 複合索引每個列都需要計算,全部列都生效了纔是充分利用,上面例子三個列都生效,所以是充分利用了索引
key_len總結
- 變長字段需要額外的2個字節(VARCHAR值保存時只保存需要的字符數,另加一個字節來記錄長度(如果列聲明的長度超過255,則使用兩個字節),所以VARCAHR索引長度計算時候要加2),固定長度字段不需要額外的字節。
- NULL都需要1個字節的額外空間,所以索引字段最好不要爲NULL,因爲NULL讓統計更加複雜並且需要額外的存儲空間。
- 複合索引有最左前綴的特性,如果複合索引能全部使用上,則是複合索引字段的索引長度之和,這也可以用來判定複合索引是否部分使用,還是全部使用。
- 一張表中不能全是索引,底層維護索引效率太低了。並且之後的查詢都是從索引拿,就是都使用覆蓋索引了
四、索引策略優化
索引一般都是根據sql語句來作的index(a,b,c),但是作成之後,索引的順序就是對sql造成影響
sql沒有索引時, where掃描是從右到左的
有索引,按照索引定義的方式來執行 比如有index(a,b,c),執行順序就是a,b,c,這個跟後面where的順序無關,但是where中有a才能執行,有bc沒a還是不能執行
十大索引策略:
1、儘量全值匹配 | 就是準確不用like |
2、最佳左前綴法則 | 如果是複合索引,要遵循最左前綴法則,指的是查詢從索引的最左前列開始並且不跳過索引中的列 |
3、不在索引列上做任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描 | |
4、範圍條件放最後 | 意思是sql有範圍查詢,定義複合索引應該把它放最後(存儲引擎不能使用索引中範圍條件右邊的列) |
5、儘量使用覆蓋索引 | 只訪問索引的查詢(索引列和查詢列一致),減少select * 查出來的都是索引,叫做覆蓋索引 |
6、mysql 在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃描 | |
7、注意null/not null對索引的可能影響 | |
8、Like查詢要當心,%不要放第一 | |
9、字符類型加引號 | |
10、OR改UNION效率高 |
CREATE INDEX age_name_sex_index ON id(age,name,sex)
2、最佳左前綴法則
如果是複合索引,要遵循最左前綴法則,指的是查詢從索引的最左前列開始並且不跳過索引中的列
索引全有效
索引全失效(首個age索引不在,失效)
age索引有效(跳過了name,導致c索引失效)
4、範圍條件放最後(索引定義時是age在第一,使用範圍,導致其後的索引都失效)
設置索引應該根據SQL來定義索引,索引應該設置成CREATE INDEX age_name_sex_index ON id(name,sex,age)
5、儘量使用覆蓋索引
針對下列情況,可以使用全索引覆蓋
使用全索引覆蓋,SELECT age,name,sex FROM id WHERE age<2 AND name='lisi' AND sex='1'(age、name、sex都是索引列)
7、Like查詢要當心
like 後第一個加%時,影響索引及後續索引
所以Like的%不要加在第一個
索引優化口訣:
全值匹配我最愛,最左前綴要遵守;
帶頭大哥不能死,中間兄弟不能斷;
索引列上少計算,範圍之後全失效;
LIKE百分寫最右,覆蓋索引不寫*;
不等空值還有OR,索引影響要注意;
VARCHAR引號不可丟, SQL優化有訣竅
題目:
index(a,b,c)
Where語句 | 索引是否被使用 |
where a = 3 | a被使用 |
where a = 3 and b = 5 | ab被使用 |
where a = 3 and b = 5 and c = 4 | abc被使用 |
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4 | 沒有被使用 |
where a = 3 and c = 5 | a被使用 |
where a = 3 and b > 4 and c = 5 | ab被使用 |
where a = 3 and b like 'kk%' and c = 4 | abc被使用 |
where a = 3 and b like '%kk' and c = 4 | a被使用 |
where a = 3 and b like '%kk%' and c = 4 | a被使用 |
where a = 3 and b like 'k%kk%' and c = 4 | abc被使用 |