MySQL 索引

1. 索引作用

作用: 提供類似于書中的目錄的作用,目的是為了優(yōu)化查詢

2. 索引的種類(算法)

B樹索引
hash索引
R樹索引
full text
GIS

3. B樹 基于不同的查找算法分類

1.) B - tree
2.) B + tree 在范圍查詢方面提供了更好的性能(> >= < <= )


image.png

3.) B*thee

4. 按功能上分類

4.1 輔助索引(s)如何構(gòu)建B樹結(jié)構(gòu)

(1). 索引是基于表中,列(索引鍵)的值生成的B樹結(jié)構(gòu)
(2). 首先提取此列所有的值,進(jìn)行自動排序
(3). 將排好序的值,均勻的分布到索引樹的葉子節(jié)點(diǎn)中(16K)
(4). 然后生成此索引鍵值所對應(yīng)得后端數(shù)據(jù)頁的指針
(5). 生成枝節(jié)點(diǎn)和根節(jié)點(diǎn),根據(jù)數(shù)據(jù)量級和索引鍵長度,生成合適的索引樹高度
id name age gender
select * from t1 where id=10;
問題: 基于索引鍵做where查詢,對于id列是順序IO,但是對于其他列的查詢,可能是隨機(jī)IO.

4.2 輔助索引分類

1.) 普通的單列輔助索引
2.) 聯(lián)合索引 (多列作為索引條件,生成索引樹,)
3.) 唯一索引 (索引列的值都是唯一的)

4.2 聚集索引 (C)

4.2.1 前提

(1)表中設(shè)置了主鍵,主鍵列就會自動被作為聚集索引.
(2)如果沒有主鍵,可以選擇唯一鍵作為聚集索引.
(3)聚集索引必須在建表時才有意義,一般是表的無關(guān)列(ID)

4.2.2 輔助索引(S)怎么構(gòu)建B樹結(jié)構(gòu)

(1) 在建表時,設(shè)置了主鍵列(ID)
(2) 在將來錄入數(shù)據(jù)時,就會按照ID列的順序存儲到磁盤上.(我們又稱之為聚集索引組織表)
(3) 將排好序的整行數(shù)據(jù),生成葉子節(jié)點(diǎn).可以理解為,磁盤的數(shù)據(jù)頁就是葉子節(jié)點(diǎn)

4.3 聚集索引和輔助索引構(gòu)成區(qū)別

聚集索引只能有一個,非空唯一,一般時主鍵
輔助索引,可以有多個,是配合聚集索引使用的
聚集索引葉子節(jié)點(diǎn),就是磁盤的數(shù)據(jù)行存儲的數(shù)據(jù)頁
MySQL是根據(jù)聚集索引,組織存儲數(shù)據(jù)的,如果創(chuàng)表時沒有沒有聚集索引,數(shù)據(jù)會隨機(jī)分配儲存在表中的,
輔助索引,只會提取索引鍵值,進(jìn)行自動排序生成B樹結(jié)構(gòu)

5. 索引樹的高度

影響索引樹的高度因素
1.) 數(shù)據(jù)量級(行數(shù))
解決辦法: 分表 分庫 分布式
2.) 索引列值長度
解決辦法: 前綴索引
3.) 數(shù)據(jù)類型
解決辦法: 可變長度字符串,用varchar, 固定填寫的,用enum

6. 索引命令

6.1 創(chuàng)建索引

1) 普通的單列輔助索引
alter  table 表名 add index  索引名(列);
2) 聯(lián)合索引
alter   table 表名 add index   索引名(列1,列2);
注: 創(chuàng)建聯(lián)合索引時, 列的先后順序不一樣,搜索的時間也不一樣
3) 前綴索引
alter  table 表名 add index  索引名(列(取列的數(shù)據(jù)前多少位));
4)  唯一索引
 alter  table 表名 add unique index  索引名(列);
注: 建立唯一索引時.列內(nèi)的每行字符必須是唯一的,不能有重復(fù)

6.2 查看索引

desc   表名;
只顯示那列創(chuàng)建了索引和索引類型
show index from 表名;
顯示索引名和索引列

6.3 刪除索引

alter  table 表名  drop  index   索引名;

7. 執(zhí)行計(jì)劃獲取分析

(1)獲取到的是優(yōu)化器選擇完成的,他認(rèn)為代價最小的執(zhí)行計(jì)劃.
作用: 語句執(zhí)行前,先看執(zhí)行計(jì)劃信息,可以有效的防止性能較差的語句帶來的性能問題.
如果業(yè)務(wù)中出現(xiàn)了慢語句,我們也需要借助此命令進(jìn)行語句的評估排惨,分析優(yōu)化方案。
(2) select 獲取數(shù)據(jù)的方法
1.) 全表掃描(應(yīng)當(dāng)盡量避免,因?yàn)樾阅艿?
2.) 索引掃描
3.) 獲取不到數(shù)據(jù)

7.1 執(zhí)行計(jì)劃獲取

desc select [查詢的內(nèi)容] from  表   where   [條件] ...
image.png

7.2 表中的中的信息

1.) table: 數(shù)據(jù)在的表
2.) possible_keys: 可能使用的索引
3.) key: 查詢時使用的索引
4.) type: 索引類型
5.) extra: 額外的信息

7.3 type 類型

從劣到優(yōu)(all index range ref eq_ref sysem,const)

7.3.1 all

不使用索引, 全表掃描.

1.) 查詢條件列 沒用索引
2.) 查詢條件中使用 <> , not in , like %條例%
注: 使用的輔助索引列 會出現(xiàn)這種情況
對于聚焦索引列,以上情況依然使用索引

7.3.2 index

全索引掃描

1.) 查詢需要獲取整個索引樹中的值時,
2.) 聯(lián)合索引中,任何一個非最左列作為查詢條件時,

7.3.3 range

索引范圍掃描

1.) 輔助索引 條件為 > < >= <= like in or
2.) 主鍵 <> , not in

例子:
1. 
desc  select  * from city where id<5;
2. 
desc select  * from city where countrycode like 'CH%';
3. 
desc  select  * from city where countrycode in ('CHN','USA');

注意: 
1和2例子中,可以享受到B+樹的優(yōu)勢,但是3例子中是不能享受的.
所以,我們可以將3號列子改寫:

desc select * from city where countrycode='CHN'
union all 
select * from city where countrycode='USA';

7.3.4 ref

非唯一性索引,等值查詢

7.3.5 eq_ref

在多表連接時,連接條件使用了唯一索引(uk pK)

7.3.6 system,const

唯一索引的等值查詢

7.4 extra 額外的信息

filesort ,文件排序

如果出現(xiàn) 說名搜索到的結(jié)果有額外的排序了
結(jié)論:
1.當(dāng)我們看到執(zhí)行計(jì)劃extra位置出現(xiàn)filesort,說明由文件排序出現(xiàn)
2.觀察需要排序(ORDER BY,GROUP BY ,DISTINCT )的條件,有沒有索引

  1. 根據(jù)子句的執(zhí)行順序,去創(chuàng)建聯(lián)合索引

7.4 聯(lián)合索引

1.) 當(dāng)判斷語句中出現(xiàn)的是 and 時 ,查詢時不考慮聯(lián)合索引中的順序,優(yōu)化器會自動調(diào)整 判斷條件的先后順序
注: 我們在這種情況下建索引時,需要考慮哪個列的唯一值更多,哪個放在索引左邊.

2.) 如果查詢語句中出現(xiàn)了多個判斷句(如where,
group by, 等) ,在建立索引時,要按句子的順序進(jìn)行建立.
注: having 一般情況下是 不走索引的

面試題
題目意思: 我們公司業(yè)務(wù)慢,請你從數(shù)據(jù)庫的角度分析原因
1.mysql出現(xiàn)性能問題,我總結(jié)有兩種情況:
(1)應(yīng)急性的慢:突然夯住
應(yīng)急情況:數(shù)據(jù)庫hang(卡了,資源耗盡)
處理過程:
1.show processlist; 獲取到導(dǎo)致數(shù)據(jù)庫hang的語句

  1. explain 分析SQL的執(zhí)行計(jì)劃,有沒有走索引,索引的類型情況
  2. 建索引,改語句
    (2)一段時間慢(持續(xù)性的):
    (1)記錄慢日志slowlog,分析slowlog
    (2)explain 分析SQL的執(zhí)行計(jì)劃,有沒有走索引,索引的類型情況
    (3)建索引,改語句

8 索引的應(yīng)用范圍

業(yè)務(wù)

1.產(chǎn)品的功能
2.用戶的行為
"熱"查詢語句 --->較慢--->slowlog
"熱"數(shù)據(jù)

8.1 建立索引的原則

為了使索引的使用效率更高峦阁,在創(chuàng)建索引時宅倒,必須考慮在哪些字段上創(chuàng)建索引和創(chuàng)建什么類型的索引.

1.)   建表時一定要有主鍵,一般是個無關(guān)列, 用于建立聚集索引
2.) 選擇唯一性索引
       唯一性索引的值是唯一的慎璧,可以更快速的通過該索引來確定某條記錄偷溺。
       例如逮栅,學(xué)生表中學(xué)號是具有唯一性的字段悴势。為該字段建立唯一性索引可以很快的確定某個學(xué)生的信息。
      如果使用姓名的話措伐,可能存在同名現(xiàn)象特纤,從而降低查詢速度。
優(yōu)化方案:
      (1) 如果非得使用重復(fù)值較多的列作為查詢條件(例如:男女),可以將表邏輯拆分
      (2) 可以將此列和其他的查詢類,做聯(lián)和索引
3.)  經(jīng)常需要where 废士、ORDER BY叫潦、GROUP BY,join on等操作的字段時  可以建立聯(lián)合索引
4.) 如果索引字段的值很長蝇完,最好使用值的前綴來索引官硝。
5.) 限制索引的數(shù)目
      索引的數(shù)目不是越多越好。
      可能會產(chǎn)生的問題:
          (1) 每個索引都需要占用磁盤空間短蜕,索引越多氢架,需要的磁盤空間就越大。
          (2) 修改表時朋魔,對索引的重構(gòu)和更新很麻煩岖研。越多的索引,會使更新表變得很浪費(fèi)時間。
          (3) 優(yōu)化器的負(fù)擔(dān)會很重,有可能會影響到優(yōu)化器的選擇.
          percona-toolkit中有個工具,專門分析索引是否有用
6.) 刪除不再使用或者很少使用的索引
7.)  大表加索引,要在業(yè)務(wù)不繁忙期間操作
8.) 盡量少在 要經(jīng)常更新數(shù)據(jù)的列 上建立索引

8.2 查詢時不走索引

1.) 沒有查詢條件孙援,或者查詢條件沒有建立索引

在業(yè)務(wù)數(shù)據(jù)庫中害淤,特別是數(shù)據(jù)量比較大的表。是沒有全表掃描這種需求拓售。
    1窥摄、對用戶查看是非常痛苦的。
    2础淤、對服務(wù)器來講毀滅性的
優(yōu)化方案:
1.) 每次只顯示一定量的,(limit  10)
2.) 創(chuàng)建索引,或換成有索引的列進(jìn)行搜索

2.) 查詢的結(jié)果集崭放,超過了總數(shù)行數(shù)25%,優(yōu)化器覺得就沒有必要走索引了鸽凶。

優(yōu)化方案:
1.) 每次只顯示一定量的,(limit  10)
2.) 如果業(yè)務(wù)允許,可使用 nosql型數(shù)據(jù)庫

3.) 索引本身失效币砂,統(tǒng)計(jì)數(shù)據(jù)不真實(shí)

索引有自我維護(hù)的能力。
對于表內(nèi)容變化比較頻繁的情況下玻侥,有可能會出現(xiàn)索引失效决摧。
一般是刪除重建
現(xiàn)象:
有一條select語句平常查詢時很快,突然有一天很慢,會是什么原因
select?  --->索引失效,,統(tǒng)計(jì)數(shù)據(jù)不真實(shí)
DML ?   --->鎖沖突

4.) 查詢條件使用函數(shù)在索引列上使碾,或者對索引列進(jìn)行運(yùn)算蜜徽,運(yùn)算包括(+,-票摇,*拘鞋,/,! 等)

例子:
錯誤的例子:select * from test where id-1=9;
正確的例子:select * from test where id=10;
算術(shù)運(yùn)算
函數(shù)運(yùn)算
子查詢

5.) 10.2.5 隱式轉(zhuǎn)換導(dǎo)致索引失效.這一點(diǎn)應(yīng)當(dāng)引起重視.也是開發(fā)中經(jīng)常會犯的錯誤.

這樣會導(dǎo)致索引失效. 錯誤的例子:
mysql> alter table tab add index inx_tel(telnum);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc tab;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id    | int(11)    | YES  |    | NULL    |      |
| name  | varchar(20) | YES  |    | NULL    |      |
| telnum | varchar(20) | YES  | MUL | NULL    |      |
+--------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> explain  select * from tab where telnum='1333333';
+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref  | rows | Extra                |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+

|  1 | SIMPLE      | tab  | ref  | inx_tel      | inx_tel | 63      | const |    1 | Using index condition |
+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+
1 row in set (0.00 sec)
mysql> explain  select * from tab where telnum=1333333;(telnum 創(chuàng)建庫時設(shè)置的為字符,查詢時有用數(shù)字類型搜索的)
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra      |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tab  | ALL  | inx_tel      | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
``
>6.) <>   not in 不走索引(輔助索引)

單獨(dú)的>,<,in 有可能走矢门,也有可能不走盆色,和結(jié)果集有關(guān),盡量結(jié)合業(yè)務(wù)添加limit
or或in 盡量改成union

>7.)  like "%_" 百分號在最前面不走
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祟剔,一起剝皮案震驚了整個濱河市隔躲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌物延,老刑警劉巖宣旱,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叛薯,居然都是意外死亡浑吟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門耗溜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來组力,“玉大人,你說我怎么就攤上這事抖拴×亲郑” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長候衍。 經(jīng)常有香客問我笼蛛,道長,這世上最難降的妖魔是什么蛉鹿? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任伐弹,我火速辦了婚禮,結(jié)果婚禮上榨为,老公的妹妹穿的比我還像新娘惨好。我一直安慰自己,他們只是感情好随闺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布日川。 她就那樣靜靜地躺著,像睡著了一般矩乐。 火紅的嫁衣襯著肌膚如雪龄句。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天散罕,我揣著相機(jī)與錄音分歇,去河邊找鬼。 笑死欧漱,一個胖子當(dāng)著我的面吹牛职抡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播误甚,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缚甩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窑邦?” 一聲冷哼從身側(cè)響起擅威,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冈钦,沒想到半個月后郊丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞧筛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年厉熟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驾窟。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡庆猫,死狀恐怖认轨,靈堂內(nèi)的尸體忽然破棺而出绅络,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布恩急,位于F島的核電站杉畜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衷恭。R本人自食惡果不足惜此叠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望随珠。 院中可真熱鬧灭袁,春花似錦、人聲如沸窗看。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽显沈。三九已至软瞎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拉讯,已是汗流浹背涤浇。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魔慷,地道東北人只锭。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像院尔,于是被迫代替她去往敵國和親纹烹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容