「MySQL 系列」- 索引的創建與使用

如何建立索引

在建立表的時候建立索引:html

其中關鍵字 INDEX 能夠用 KEY 替代,INDEX 前面能夠加上索引的類型 UNIQUE | FULLTEXT | SPATIAL | NORMAL,默認是 NORMALjava

CREATE TABLE `student` (
  `id` bigint NOT NULL,
  `name` varchar(30),
  PRIMARY KEY (`id`),
  INDEX `idx_name` (`name`)  -- 對 name 字段加上名爲 idx_name 的索引
)
複製代碼

對已經存在的表添加索引:mysql

ALTER TABLE student ADD INDEX idx_name (`name`)
複製代碼

建立索引的注意事項

選擇合適的字段建立索引

並非每一個字段都適合建立索引,索引的建立也是要消耗磁盤空間的,並非說索引就越多越好git

在這裏分享一個xiao ji si,InnoDB 表最多能夠包含 1017列,最多建立 64個 二級索引面試

傳送門:>>>>>>>官方文檔<<<<<<<<sql

1. 儘可能選擇不爲 null 的字段創建索引

對於 Mysql 來講,含有空值的列很難進行查詢優化,若是頻繁查詢的值又避免不了爲 null,能夠考慮使用 0,1 或者空字符這些短字符串進行替代。若是索引的字段能夠爲 NULL,索引的效率會降低不少,由於它們使得索引、索引的統計信息以及比較運算更加複雜markdown

2. 選擇區分度大列做爲索引

舉個例子,一張學生表裏面有個字段是性別 sex, 它裏面存的是男和女,各佔約百分之五十,那這樣即使你創建了索引,用哪一個值都是搜出一半來,那這樣還不如不建索引ide

MySQL有一個查詢優化器,查詢優化器發現某個值出如今表的數據行中的百分比很高的時候,它通常會忽略索引,進行全表掃描函數

慣用的百分比界線是"30%"。(匹配的數據量超過必定限制的時候查詢器會放棄使用索引(這也是索引失效的場景之一哦)oop

3. 被頻繁查詢字段、做爲查詢條件

以上字段均可以考慮設計上索引

例:對於學生表(student)和成績表(grade),假設有這麼一條語句被頻繁執行:

-- 下班準備去幸福小區,爆破成績不及格的學生
select name, age from student a
left join grade b on a.id = b.student_id 
where a.address like '%幸福小區%' and b.grade < 60
複製代碼

對於 student 表,能夠創建索引的字段有 name、age、address、birthday,對於 grade 表,在 student_id 創建索引,能夠大大提升連表查詢的速度

4. 被用於 group byorder by 的字段

order by後面的字段創建索引,這樣在查詢的時候就不須要再去作一次排序了,由於咱們都已經知道了創建索引以後在B+樹中的記錄都是排序好的

group by 和 order by 實際上是相似,因此將這兩個放在一塊兒說了

由於在group by 的時候也要先根據 group by 後面的字段排序,而後在執行聚合操做

若是 group by 後面的字段沒有排序,那麼這個時候MySQL是須要先進行排序的,這樣就會產生臨時表,一個排好序的臨時表,而後再在臨時表中執行聚合操做,這樣子固然效率很低了,若是 group by 後面的字段已經創建了索引,那麼MySQL 就不須要再去排序,也就不會產生臨時表

5. 頻繁更新的字段建立索引要慎重

SQL優化中,合理的創建索引算是基本操做了。雖然索引能帶來查詢上的效率提高,可是索引的成本也是不小的,索引會佔用磁盤空間,而且下降添加、刪除、和更新的速度。若是一個字段不被常常查詢,可是又常常被更新,那麼便不該該在這個字段上加索引


建立索引的其餘建議

1. 儘可能建立聯合索引而不是單列索引

由於索引是須要佔用磁盤空間的,能夠簡單理解爲每一個索引都對應着一顆 B+樹。若是一個表的字段過多,索引過多,那麼當這個表的數據達到一個體量後,索引佔用的空間也是不少的,且修改索引時,耗費的時間也是較多的。若是是聯合索引,多個字段在一個索引上,那麼將會節約很大磁盤空間,且修改數據的操做效率也會提高

2. 避免冗餘索引

冗餘索引指的是索引的功能相同,可以命中索引(a, b)就確定能命中索引(a) ,那麼索引(a)就是冗餘索引。如(name,city )和(name )這兩個索引就是冗餘索引,可以命中前者的查詢確定是可以命中後者的 在大多數狀況下,都應該儘可能擴展已有的索引而不是建立新索引

3. 考慮在字符串類型的字段上使用前綴索引代替普通索引

前綴索引僅限於字符串類型,較普通索引會佔用更小的空間,因此能夠考慮使用前綴索引帶替普通索引


使用索引的注意事項

索引並非說建立好以後就可無論,良好的索引須要開發人員的長期維護

首先索引對於中到大型表索引都是很是有效的,可是特大型表的話維護開銷會很大,不適合建索引,對於小型表來講,查詢所有數據的時間可能比遍歷索引的時間還要短,不須要建立索引

其次須要刪除長期未使用的索引也是有必要的,不使用的索引不只佔用着磁盤空間,並且會形成沒必要要的性能損耗,Mysql5.7 後能夠經過查詢 sys.schema_unused_indexes 表來獲取長期未使用的索引


會使索引失效的幾種狀況

1. 在查詢條件中對索引列使用函數或進行運算

若是是已經創建好的索引的字段在使用的時候執行了函數操做,那麼這個索引就使用不到了

由於MySQL爲該索引維護的B+樹就是基於該字段原始數據的,若是正在使用過程當中加了函數,MySQL就不會認爲這個是原來的字段,那確定不會走索引了

若是非要讓函數走索引,能夠在建立索引的時候把函數帶上

例:

SELECT * FROM student WHERE round(age) = 2;
複製代碼

上面語句會使索引 idx_age 失效,若是非要讓這條語句走索引,能夠這樣建立:

create index idx_age_round on student(round(age)); 
複製代碼

其次,在 where 中對索引列進行了運算,也會使索引失效

2. 在 like 條件中使用 % 開頭

select * from student where name like '%bc%'
複製代碼

就上面的語句來講,索引是不生效的,想要索引生效,須要把前綴的 % 去掉

3. 使用了 or 條件

若是想要讓 or 條件走索引,須要把 or 條件中的全部字段加上索引

4. 最左匹配原則

最左匹配原則就是指在聯合索引中,若是你的 sql 語句中用到了聯合索引中的最左邊的索引,那麼這條 sql 語句就能夠利用這個聯合索引去進行匹配,當遇到範圍查詢(>、<、between、like)就會中止匹配


Reference

掘金:我面試幾乎必問:你設計索引的原則是什麼?怎麼避免索引失效?

JavaGuide:使用索引的一些建議

相關文章
相關標籤/搜索