1.最左字首原則
一般在where條件中兩個及以上欄位時,我們會建聯合索引。若查詢語句:select name,address,country from people where name='***' and country='***';
索引建立有下面兩種方案 a(name,country) b(country,name)。將選擇性好的字段放在前面(因為people name重複率相對於country低),所以應該建name,country索引。無論where name='***' and country='...' 還是 where country='***' and name='...',mysql會幫你優化查詢條件,不用擔心查詢順序。若組合索引有四五個字段,那麼按照選擇性進行排列,選擇性好的字段放前面。
假設create index idx_name_address_country on t1(name,address,country);按照最左匹配有下面幾個原則,判斷查詢是否會走索引
1.1 若查詢的條件不包含索引的最左列,無法使用索引
where name=*** and address=*** and country=***
可以走索引
where name=***
可以走索引
where name=*** and country=***
可以走部分索引
where address=***
不可以走索引,不包含最左列name
where country=*** and name=***
不可以走索引,不包含最左列name,mysql沒有優化是因為索引欄位裡還包含了address
1.2 查詢包含了索引中所有的字段,查詢效率較高,如果只包含了索引中部分字段,查詢效率會低一些
where name=*** 和 where name=*** and country=*** 雖然都包含了索引最左列,也可以走索引,但是他們都只能根據name欄位進行過濾資料,效率比 where name=*** and address=*** and country=***低很多
1.3 如果組合索引中已經包含了字段,可以不用單獨再建索引,提高索引使用率
比如已經有了索引(name,address,country),就不需要在單獨建索引(name)或 (name,address)
1.4 無法對組合索引中多個字段進行範圍查詢,只能按照最左原則,對最左邊第乙個範圍查詢有效
例如create index idx_a_b_c on table(a,b,c); 紅字表示不走索引
a=5索引
a between 5 and 10
索引a=5 and b between 5 and 10
索引a between 5 and 10 and b=5
部分索引
a in (1,2,3) and b=5
索引b=5 and ...
不走索引
a = 5 and b > 5 and c > 10
部分索引
1.5 覆蓋索引: 即索引中包含了查詢中的所有字段,可以避免回表查詢,減少訪問磁碟次數
1.6 利用索引的有序性,進行排序,有效減少cpu開銷,需要遵從最左原則
採用idx_a_b_c,下列查詢可使用索引
order by a
order by a,b
order by a desc, b desc
where a = 5 order by b [asc\desc]
where a > 5 order by a [asc\desc]
where a = 5 order by a,b
order by b
order by a[asc\desc] ,b [desc/asc]
1.7 其他設計
join查詢中連線字段建立索引
只返回需要的字段,避免使用select *
不使用全模糊查詢 like '%***%』(無法走索引),可以使用like '***%'(走索引)
不等於查詢not in , =(無法走索引)
型別不匹配,比如存了數值的字串型別字段(如手機號),查詢時記得不要丟掉值的引號,否則無法用到該欄位相關索引
2.最**擇性原則
該不該在乙個欄位上建立索引,主要考慮選擇性,選擇性就是這個字段裡面的值重複率高不高。公式是 distinct(建索引的列)/count(*) ,區間範圍在[0,1],如果是0,表示該列中所有值都一樣,如果是1,表示該列有唯一約束。該比例越趨向於1,查詢效能越好。這是由b+tree的性質決定的。一般情況,status(狀態)、is_deleted(是否刪除)、***(性別)列都不建議建索引。單號、userid等建議放在最前面。
3.總結
索引設計的規約(摘自螞蟻金服&集團db設計規範)
索引不是越多越好,越多的索引帶來的就是更高的索引維護成本,包含cpu計算消耗,索引建立時增加的io開銷等,因此一定要合理建立索引;
表被索引列必須定義為not null,並設定default值;
超過三個表禁止join。需要join的字段,資料型別保持絕對一致;多表關聯查詢時,保證被關聯的字段需要有索引;
在varchar欄位上建立索引時,必須指定索引長度,沒必要對全欄位建立索引,根據實際文字區分度決定索引長度。一般對字串型別資料,長度為20的索引,區分度會高達90%以上,可以使用count(distinct left(列名, 索引長度))/count(*)的區分度來確定。
頁面搜尋嚴禁左模糊或者全模糊,如果需要請走搜尋引擎來解決。索引檔案具有b-tree的最左字首匹配特性,如果左邊的值未確定,那麼無法使用此索引;
如果有order by的場景,請注意利用索引的有序性。order by 最後的字段是組合索引的一部分,並且放在索引組合順序的最後,避免出現file_sort的情況,影響查詢效能。正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有範圍查詢,那麼索引有序性無法利用,如:where a>10 order by b; 索引a_b無法排序。
mysql 索引長度和區分度
首先 索引長度和區分度是相互矛盾的,索引長度太短,那麼區分度就很低,吧索引長度加長,區分度就高,但是索引也是要佔記憶體的,所以我們需要找到乙個平衡點 那麼這個平衡點怎麼來定?比如使用者表有個字段 username 要給他加索引,問題是索引長度多少合適?其實我們知道 百家姓裡面有百多個姓 但是大多數人...
MySQL 索引長度和區分度
首先 索引長度和區分度是相互矛盾的,索引長度太短,那麼區分度就很低,吧索引長度加長,區分度就高,但是索引也是要佔記憶體的,所以我們需要找到乙個平衡點 那麼這個平衡點怎麼來定?比如使用者表有個字段 username 要給他加索引,問題是索引長度多少合適?其實我們知道 百家姓裡面有百多個姓 但是大多數人...
mysql 索引長度與區分度的選擇
理想的索引 索引長度直接影響索引檔案的大小,影響增刪改的速度,並間接影響查詢速度 占用記憶體多 針對列中的值,從左往右擷取部分,來建索引 1 截的越短,重複度越高,區分度越小,索引效果越不好 2 截的越長,重複度越低,區分度越高,索引效果越好,但帶來的影響也越大 增刪改變慢,併間影響查詢速度.所以,...