Mysql索引使用策略

索引的作用-一個例子

索引對查詢的速度有著至關重要的影響崇决,理解索引也是進行數(shù)據(jù)庫性能調優(yōu)的起點牺六。
考慮如下情況颤枪,假設數(shù)據(jù)庫中一個表有10^6條記錄,DBMS的頁面大小為4K淑际,并存儲100條記錄畏纲。
如果沒有索引,查詢將對整個表進行掃描春缕,最壞的情況下盗胀,如果所有數(shù)據(jù)頁都不在內存,
需要讀取104個頁面淡溯,如果這104個頁面在磁盤上隨機分布读整,需要進行10^4次I/O簿训,
假設磁盤每次I/O時間為10ms(忽略數(shù)據(jù)傳輸時間)咱娶,則總共需要100s(但實際上要好很多很多)。
如果對之建立B-Tree索引强品,則只需要進行l(wèi)og100(10^6)=3次頁面讀取膘侮,最壞情況下耗時30ms。
這就是索引帶來的效果的榛,很多時候琼了,當你的應用程序進行SQL查詢速度很慢時,應該想想是否可以建索引。

索引的優(yōu)點:

  1. 減少了服務器需要掃描的數(shù)據(jù)量
  2. 避免排序和臨時表
  3. 將隨機IO變?yōu)轫樞騃O

聚集索引和非聚集索引的區(qū)別及優(yōu)缺點

  1. 聚集索引一個表只能有一個雕薪,而非聚集索引一個表可以存在多個
  2. 聚集索引存儲記錄是物理上連續(xù)存在昧诱,而非聚集索引是邏輯上的連續(xù),物理存儲并不連續(xù)
  3. 聚集索引:物理存儲按照索引排序所袁;聚集索引是一種索引組織形式盏档,索引的鍵值邏輯順序決定了表數(shù)據(jù)行的物理存儲順序
      非聚集索引:物理存儲不按照索引排序;非聚集索引則就是普通索引了燥爷,僅僅只是對數(shù)據(jù)列創(chuàng)建相應的索引蜈亩,不影響整個表的物理存儲順序.
  4. 索引是通過二叉樹的數(shù)據(jù)結構來描述的,我們可以這么理解聚簇索引:索引的葉節(jié)點就是數(shù)據(jù)節(jié)點前翎。而非聚簇索引的葉節(jié)點仍然是索引節(jié)點稚配,只不過有一個指針指向對應的數(shù)據(jù)塊。

優(yōu)勢與缺點:

聚集索引插入數(shù)據(jù)時速度要慢(時間花費在“物理存儲的排序”上港华,也就是首先要找到位置然后插入),查詢數(shù)據(jù)比非聚集數(shù)據(jù)的速度快

InnoDB只能還有一個聚集索引

  • 如果表中含有主鍵,則InnoDB組織數(shù)據(jù)就是通過這個聚集索引
  • 如果沒有主鍵道川,則Mysql會選擇第一個(按照聲明的順序)不允許null的unique的普通索引作為聚集索引
  • 如果沒有索引,或者索引都不是非null的唯一索引苹丸,則使用InnoDB引擎內置的ROWID作為聚集索引

InnoDB的聚集索引可以包含多列

比如在創(chuàng)建表的時候指定包含多列的主鍵愤惰,在存儲的時候按照聚集索引包含的列的前后順序來分組排序存放

InnoDB可以有多個非聚集索引

非聚集索引通過引用主鍵索引(聚集索引)來訪問或者定位數(shù)據(jù)

其他索引(普通索引)中不會保存行的物理位置,而是保存主鍵的值,所以通過"二級索引"進行查找是先找到主鍵,
再找到行,要進行二次索引查找

InnoDB中聚集索引和主鍵的關系

在InnoDB表中,其聚集索引相當于整張表赘理,而整張表也是聚集索引宦言。主鍵必然是聚集索引,而聚集索引則未必是主鍵商模。

select選擇字段是否用到索引

1- 單列索引

  • 當在where子句中在單列索引字段在數(shù)值運算的一側或者函數(shù)奠旺,那么就不會使用單列索引

select id from people where id + 1 = 5; # 不使用索引
select id from people where id = 5+1; # 使用索引
select ... from people where to_days(current_date) - to_days(date_col) <= 10; # 不使用索引

  • 對于創(chuàng)建 blob text varchar 類型字段的索引,必須指定長度施流,因為Mysql不允許這些列的完整長度
    create index index_name on table_name(varchat_columns(10))

確定前綴索引的長度:為了盡量使得單列前綴索引更有選擇性响疚,需要進行列的選擇性測試

選擇性 = 不重復的行數(shù) / 總行數(shù)
計算方式如下:

select count(left(index_column,3))/count(*) as pre_index_3,
    count(left(index_column,4))/count(*) as pre_index_4
    from database_name.table_name;

如果發(fā)現(xiàn)pre_index_4 > pre_index_3
那么就創(chuàng)建這個索引
alter table table_name add index/key index_name(index_column(4));

注意:

  • 以下不能使用前綴索引:
    order by、group by瞪醋、覆蓋索引

2- 復合索引

考慮如下索引

      CREATE TABLE `people` (
        `last_name` varchar(50)  NOT NULL,
        `first_name` varchar(50)  NOT NULL,
        `age` int(8) NOT NULL ,
        `gender` enum('m','f') NOT NULL,
        KEY `last_name` (`last_name`,`first_name`,`age`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
使用索引的情況
  1. 全值匹配
    和索引中所有列進行匹配
    select gender from people where last_name = 'Tom' and first_name = 'cat' and age=10;
    使用了符合索引的全部列
    即where子句對索引列全值匹配

  2. 匹配最左前綴列
    select gender from people where last_name = 'Tom';
    使用了復合索引的第一列

  3. 匹配列的最左前綴
    select gender from people where last_name like 'Tom%';
    使用了索引的第一列
    注意like子句開頭不能包含通配符(%,_)忿晕,而且必須是常量字符串,而不能是其他字段名银受,否則使用不到索引

  1. 匹配范圍(where子句中只有第一個符合最左前綴列的范圍匹配可以使用到索引)
    要求:1. 范圍列是最左前綴列践盼;只能匹配第一個范圍列
    select gender from people where last_name between 'Alice' and 'Davis';
    使用了符合索引的第一列
    select gender from people where first_name between 'Alice' and 'Davis';
    不滿足要求,所以不會使用索引
    表示范圍的可以使用到索引:
    <,<=,=,>,>=
    between and
    in(num1,num2)
    注意 != , <> 這些不等于不能使用索引宾巍,而是應該使用 column > num or column < num 來等價替換咕幻,來使用索引
  1. where子句先是精確匹配再是范圍匹配
    select gender from people where last_name = 'James' and first_name between 'Alice' and 'Davis';
    使用索引的第一列(全匹配)和第二列(范圍匹配)

  2. 創(chuàng)建索引時指定列的排序模式,排序時使用相同的排序順序或則完全相反的排序順序
    創(chuàng)建索引:CREATE INDEX idx_example ON table1 (col1 ASC, col2 DESC, col3 ASC);
    1-相同順序排序:Select col1, col2, col3 from table1 order by col1 ASC, col2 DESC, col3 ASC;
    2-完全逆序排序Select col1, col2, col3 from table1 order by col1 DESC, col2 ASC, col3 DESC;
    3-不完全順序排序 Select col1, col2, col3 from table1 order by col1 ASC, col2 ASC, col3 ASC
    排序使用到的索引只有1顶霞,2肄程;3沒有使用到索引。

不使用索引列的情況
  1. 不是索引的最左前綴列
  2. 不是單列索引的列的最左前綴,主要限制為 like子句的開頭包含通配符前綴
  3. 跳過中間列蓝厌,只能使用中間列前面的那些索引列
  4. 一個范圍匹配(包括 like子句)的后面無法再使用索引
  5. where 子句中使用了索引玄叠,則其后面的order by group by子句沒有辦法再使用索引
  6. 索引的列在運算符的一側,即緊鄰的是 +拓提,- / *這些運算符诸典,而不是緊鄰 = ,<,>,>=,<= 這些符號崎苗;
    或者對索引列使用函數(shù)狐粱;這些都將不能使用索引。
最左前綴和對and的查詢優(yōu)化

待續(xù)

可以使用到索引的子句

待續(xù)

多個子句使用索引的情況

每一個select查詢只能使用一個索引
待續(xù)

where中是用or連接的查詢條件

待續(xù)

where中在索引列之間包含普通列

待續(xù)

3- 覆蓋索引

如果一個索引包含(覆蓋)所有需要查詢的字段的值胆数,我們就稱為覆蓋索引
即 select 子句選擇的字段都出現(xiàn)在定義多列索引的字段中肌蜻。
因為索引中包含查詢的所有字段,所以就不需要根據(jù)索引回數(shù)據(jù)行獲取其他非索引列的數(shù)據(jù)必尼,
而是直接將索引中的數(shù)據(jù)直接返回蒋搜。

創(chuàng)建索引
alter table table_name add index index_name(column_1,column_2,column_3);

查詢時使用覆蓋索引
select column_2 from table_name where column_2 = 8;
注意這里沒有使用最左前綴列,而是通過索引覆蓋來使用索引

覆蓋索引的限制

待續(xù)

4- 不同類型索引的選擇問題

如果一個列被多個不同類型索引包含判莉,那么如何選擇索引的問題

待續(xù)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末豆挽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子券盅,更是在濱河造成了極大的恐慌帮哈,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锰镀,死亡現(xiàn)場離奇詭異娘侍,居然都是意外死亡,警方通過查閱死者的電腦和手機泳炉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進店門憾筏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人花鹅,你說我怎么就攤上這事氧腰。” “怎么了刨肃?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵古拴,是天一觀的道長。 經常有香客問我之景,道長斤富,這世上最難降的妖魔是什么膏潮? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任锻狗,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘轻纪。我一直安慰自己油额,他們只是感情好,可當我...
    茶點故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布刻帚。 她就那樣靜靜地躺著潦嘶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪崇众。 梳的紋絲不亂的頭發(fā)上掂僵,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天,我揣著相機與錄音顷歌,去河邊找鬼锰蓬。 笑死,一個胖子當著我的面吹牛眯漩,可吹牛的內容都是我干的芹扭。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼赦抖,長吁一口氣:“原來是場噩夢啊……” “哼舱卡!你這毒婦竟也來了?” 一聲冷哼從身側響起队萤,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤轮锥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后要尔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體交胚,經...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年盈电,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝴簇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡匆帚,死狀恐怖熬词,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情吸重,我是刑警寧澤互拾,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站嚎幸,受9級特大地震影響颜矿,放射性物質發(fā)生泄漏。R本人自食惡果不足惜嫉晶,卻給世界環(huán)境...
    茶點故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一骑疆、第九天 我趴在偏房一處隱蔽的房頂上張望田篇。 院中可真熱鬧,春花似錦箍铭、人聲如沸泊柬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兽赁。三九已至,卻和暖如春冷守,著一層夾襖步出監(jiān)牢的瞬間刀崖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工拍摇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒲跨,地道東北人。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓授翻,卻偏偏與公主長得像或悲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子堪唐,可洞房花燭夜當晚...
    茶點故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內容