索引在mysql中也叫是一種'鍵',是存儲引擎用於快速找到記錄的一種數據結構.索引對於良好的性能很是關鍵,尤爲是當表中的數據量愈來愈大時,索引對於性能的影響愈加重要.html
索引優化應該是對查詢性能優化最有效的手段了。索引可以輕易將查詢性能提升好幾個數量級。
索引至關於字典的音序表,若是要查某個字,若是不使用音序表,則須要從幾百頁中逐頁去查。mysql
索引的目的在於提升查詢效率,本質都是不斷的縮小查詢範圍來獲得咱們想要查詢的結果.同時把隨機的時間變成順序的事件, sql
每次查找數據時把磁盤IO次數控制在一個很小的數量級,最好是常數數量級。那麼咱們就想到若是一個高度可控的多路搜索樹是否能知足需求呢?就這樣,b+樹應運而生(B+樹是經過二叉查找樹,再由平衡二叉樹,B樹演化而來)。性能優化
b+樹性質
1.索引字段要儘可能的小:IO次數取決於b+數的高度h,假設當前數據表的數據爲N,每一個磁盤塊的數據項的數量是m,則有h=㏒(m+1)N,當數據量N必定的狀況下,m越大,h越小;而m = 磁盤塊的大小 / 數據項的大小,磁盤塊的大小也就是一個數據頁的大小,是固定的,若是數據項佔的空間越小,數據項的數量越多,樹的高度越低。這就是爲何每一個數據項,即索引字段要儘可能的小,好比int佔4字節,要比bigint8字節少一半。這也是爲何b+樹要求把真實的數據放到葉子節點而不是內層節點,一旦放到內層節點,磁盤塊的數據項會大幅度降低,致使樹增高。當數據項等於1時將會退化成線性表。
2.索引的最左匹配特性:當b+樹的數據項是複合的數據結構,好比(name,age,sex)的時候,b+數是按照從左到右的順序來創建搜索樹的,好比當(張三,20,F)這樣的數據來檢索的時候,b+樹會優先比較name來肯定下一步的所搜方向,若是name相同再依次比較age和sex,最後獲得檢索的數據;但當(20,F)這樣的沒有name的數據來的時候,b+樹就不知道下一步該查哪一個節點,由於創建搜索樹的時候name就是第一個比較因子,必需要先根據name來搜索才能知道下一步去哪裏查詢。好比當(張三,F)這樣的數據來檢索時,b+樹能夠用name來指定搜索方向,但下一個字段age的缺失,因此只能把名字等於張三的數據都找到,而後再匹配性別是F的數據了, 這個是很是重要的性質,即索引的最左匹配特性。數據結構
b+樹只在葉子節點存數據ide
有利於下降樹的高度函數
穩定查詢全部數據的io次數性能
在全部的葉子節點之間添加了雙向鏈表優化
致使了全部的範圍查詢b+樹的效率比b樹高spa
彙集索引與輔助索引#InnoDB存儲引擎表是索引組織表,即表中數據按照主鍵順序存放。 而彙集索引(clustered index)就是按照每張表的主鍵構造一棵B+樹,同時葉子結點存放的即爲整張表的行記錄數據,也將彙集索引的葉子結點稱爲數據頁。 彙集索引的這個特性決定了索引組織表中數據也是索引的一部分。同B+樹數據結構同樣,每一個數據頁都經過一個雙向鏈表來進行連接。 #若是未定義主鍵,MySQL取第一個惟一索引(unique)並且只含非空列(NOT NULL)做爲主鍵,InnoDB使用它做爲聚簇索引。 #若是沒有這樣的列,InnoDB就本身產生一個這樣的ID值,它有六個字節,並且是隱藏的,使其做爲聚簇索引。 #因爲實際的數據頁只能按照一棵B+樹進行排序,所以每張表只能擁有一個彙集索引。 在多數狀況下,查詢優化器傾向於採用彙集索引。由於彙集索引可以在B+樹索引的葉子節點上直接找到數據。 此外因爲定義了數據的邏輯順序,彙集索引可以特別快地訪問針對範圍值得查詢。
彙集索引的好處之一:它對主鍵的排序查找和範圍查找速度很是快,葉子節點的數據就是用戶所要查詢的數據。如用戶須要查找一張表,查詢最後的10位用戶信息,因爲B+樹索引是雙向鏈表,因此用戶能夠快速找到最後一個數據頁,並取出10條記錄
彙集索引的好處之二:範圍查詢(range query),即若是要查找主鍵某一範圍內的數據,經過葉子節點的上層中間節點就能夠獲得頁的範圍,以後直接讀取數據頁便可
表中除了彙集索引外其餘索引都是輔助索引(Secondary Index,也稱爲非彙集索引),與彙集索引的區別是:輔助索引的葉子節點不包含行記錄的所有數據。 葉子節點除了包含鍵值之外,每一個葉子節點中的索引行中還包含一個書籤(bookmark)。該書籤用來告訴InnoDB存儲引擎去哪裏能夠找到與索引相對應的行數據。
輔助索引的存在並不影響數據在彙集索引中的組織,所以每張表上能夠有多個輔助索引,但只能有一個彙集索引。當經過輔助索引來尋找數據時,InnoDB存儲引擎會遍歷輔助索引並經過葉子級別的指針得到只想主鍵索引的主鍵,而後再經過主鍵索引來找到一個完整的行記錄。
舉例來講,若是在一棵高度爲3的輔助索引樹種查找數據,那須要對這個輔助索引樹遍歷3次找到指定主鍵,若是彙集索引樹的高度一樣爲3,那麼還須要對彙集索引樹進行3次查找,最終找到一個完整的行數據所在的頁,所以一共須要6次邏輯IO訪問才能獲得最終的一個數據頁。
1.若是條件中有or,即便其中有條件帶索引也不會使用(這也是爲何儘可能少用or的緣由) 2.對於多列索引,不是使用的第一部分,則不會使用索引 3.like查詢是以%開頭 4.若是列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引 5.若是mysql估計使用全表掃描要比使用索引快,則不使用索引 6 對小表查詢 7 提示不使用索引 8 統計數據不真實 9.單獨引用複合索引裏非第一位置的索引列.
功能
#1. 索引的功能就是加速查找 #2. mysql中的primary key,unique,聯合惟一也都是索引,這些索引除了加速查找之外,還有約束的功能
MySQL經常使用的索引
普通索引INDEX:加速查找 惟一索引: -主鍵索引PRIMARY KEY:加速查找+約束(不爲空、不能重複) -惟一索引UNIQUE:加速查找+約束(不能重複) 聯合索引: -PRIMARY KEY(id,name):聯合主鍵索引 -UNIQUE(id,name):聯合惟一索引 -INDEX(id,name):聯合普通索引
建立/刪除索引的語法
#方法一:建立表時 CREATE TABLE 表名 ( 字段名1 數據類型 [完整性約束條件…], 字段名2 數據類型 [完整性約束條件…], [UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [索引名] (字段名[(長度)] [ASC |DESC]) ); #方法二:CREATE在已存在的表上建立索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(長度)] [ASC |DESC]) ; #方法三:ALTER TABLE在已存在的表上建立索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(長度)] [ASC |DESC]) ; #刪除索引:DROP INDEX 索引名 ON 表名字;
#方式一 create table t1( id int, name char, age int, sex enum('male','female'), unique key uni_id(id), index ix_name(name) #index沒有key ); create table t1( id int, name char, age int, sex enum('male','female'), unique key uni_id(id), index(name) #index沒有key ); #方式二 create index ix_age on t1(age); #方式三 alter table t1 add index ix_sex(sex); alter table t1 add index(sex); #查看 mysql> show create table t1; | t1 | CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL, `name` char(1) DEFAULT NULL, `age` int(11) DEFAULT NULL, `sex` enum('male','female') DEFAULT NULL, UNIQUE KEY `uni_id` (`id`), KEY `ix_name` (`name`), KEY `ix_age` (`age`), KEY `ix_sex` (`sex`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 示範
1. 條件必定是創建了索引的字段,若是條件使用的字段根本就沒有建立索引,那麼索引不生效 2. 若是條件是一個範圍,隨着範圍的值逐漸增大,那麼索引能發揮的做用也越小 3. 若是使用like進行模糊查詢,那麼使用a%的形式能命中索引,%a形式不能命中索引 4. 儘可能選擇區分度高的字段做爲索引列 5. 索引列不能在條件中參與計算,也不能使用函數 6. 在多個條件以and相連的時候,會優先選擇區分度高的索引來進行查詢, 在多個條件以or相連的時候,就是從左到右依次判斷
- 避免使用select * - 使用count(*) - 建立表時儘可能使用 char 代替 varchar - 表的字段順序固定長度的字段優先 - 組合索引代替多個單列索引(因爲mysql中每次只能使用一個索引,因此常用多個條件查詢時更適合使用組合索引) - 儘可能使用短索引 - 使用鏈接(JOIN)來代替子查詢(Sub-Queries) - 連表時注意條件類型需一致 - 索引散列值(重複少)不適合建索引,例:性別不適合(就是索引的類似度高的不適合作索引)
若是咱們查詢的條件老是多個列合在一塊兒查,那麼就創建聯合索引 create index ind_mix on s1(id,email)
select * from s1 where id = 1000000 命中索引 select * from s1 where email = 'eva1000000@oldboy' 未命中索引 但凡是建立了聯合索引,那麼在查詢的時候,再建立順序中從左到右的第一列必須出如今條件中 select count(*) from s1 where id = 1000000 and email = 'eva10%'; 命中索引 select count(*) from s1 where id = 1000000 and email like 'eva10%'; 能夠命中索引 select * from s1 where id >3000 and email = 'eva300000@oldboy'; 不能命中索引
查一個數據不須要回表 select name from 表 where age = 20 不是覆蓋索引 select age from 表 where age =20 是覆蓋索引 select count(age) from 表 where age =20 是覆蓋索引
當咱們爲單獨的一列建立索引的時候: 若是條件是這一列,且使用正確就能夠命中索引 當咱們爲兩列分別建立單獨的索引的時候 若是這兩列都是條件,那麼可能只能命中期中一個條件 若是這兩列都是條件,那麼可能會命中兩個索引 - 合併索引 咱們爲多列直接建立聯合因此 條件命中聯合索引
看看mysql準備怎麼執行這條語句 能夠看到是否命中索引,計劃能命中哪些,實際命中了哪些,執行的順序,是否發生了索引合併,覆蓋索引 explain select * from s1;
文章內容來源:https://www.cnblogs.com/Eva-J/articles/10126413.html