關(guān)于索引

目錄
1.索引的概念;
2.索引的分類;
3.索引的結(jié)構(gòu)和原理;
4.索引的使用策略;
一.概念

在解釋數(shù)據(jù)庫索引之前, 我們先來回憶下平時想要查詢書中的某個章節(jié),一般情況下,我們不會漫無目的的翻閱直到找到想要找到的內(nèi)容, 而是會查找書的目錄,獲取到章節(jié)的頁碼后直接翻到對應(yīng)的頁碼; 其實在這里目錄就充當著書的索引, 來加快查詢的速度.
MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu).

二.常見索引分類
1.1唯一索引和普通索引

普通索引:是MySQL中的基本索引類型九串,允許在定義索引的列中插入重復(fù)值和空值,用來提高數(shù)據(jù)庫的查找速度寺鸥。
唯一索引:索引列的值必須唯一猪钮,但允許有NULL,如果列是字符類型胆建,插入多條為null的數(shù)據(jù)不會觸發(fā)唯一索引烤低,但是如果是多條為空字符的會觸發(fā)唯一索引。如果是組合索引笆载,則列值的組合必須唯一扑馁。
主鍵索引:是一種特殊的唯一索引,不允許有空值

主鍵和唯一索引的區(qū)別:
主鍵:
1.用于唯一標識表中的每一條數(shù)據(jù)凉驻,不能重復(fù)腻要,不能為空;
2.一般使用Long類型搭配auto_increment;(設(shè)置自增長的字段必須是主鍵,也就是說只有設(shè)為主鍵的列才可以設(shè)置為自增長).
唯一索引:
1.用于唯一標識表中的每一條數(shù)據(jù)涝登,不能重復(fù)雄家,可以為空;
2.一張表中只能有一個主鍵,但是一張表中可以有多個唯一鍵;

1.2創(chuàng)建示例
建表時添加:
CREATE TABLE `test`(
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(32) NOT NULL COMMENT '名稱',
    `code` varchar(32) NOT NULL COMMENT '編碼',
    `order_id` varchar(64) NOT NULL COMMENT '單號',
    `inserttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入庫時間',
    `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT '更新時間',
    PRIMARY KEY (`id`),   ---------------------------->主鍵
    KEY `idx_inserttime` (`inserttime`),---->普通索引(單列索引)
    UNIQUE KEY `idx_order_id` (`order_id`),----->唯一索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='測試表';

在已有表上添加:
主鍵:
ALTER TABLE `test ` ADD PRIMARY KEY(`id`);
普通索引:
ALTER TABLE `test ` ADD KEY `idx_inserttime`(`inserttime `);
唯一索引:
ALTER TABLE `test ` ADD UNIQUE KEY `idx_order_id `(`order_id `);
2.1單列索引和組合索引

單列索引:顧名思義單列索引就是以某一個字段來創(chuàng)建的索引,可以是普通索引,也可以是唯一索引胀滚。
組合索引:以2個或2個以上字段聯(lián)合創(chuàng)建的索引稱為組合索引或者多列索引趟济。

建表時添加:
CREATE TABLE `test`(
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(20) NOT NULL COMMENT '名稱',
    `code` varchar(20) NOT NULL COMMENT '編碼',
    `order_id` varchar(64) NOT NULL COMMENT '單號',
    `inserttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入庫時間',
    `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT '更新時間',
    PRIMARY KEY (`id`),   ---------------------------->主鍵
    KEY `idx_name_order_id` (`name`,`order_id`),---->組合索引(普通索引)
    UNIQUE KEY `idx_name_code` (`name`,`code`),----->組合索引(唯一索引)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='測試表';

在已有表上添加:
組合索引:
ALTER TABLE `test ` ADD KEY `idx_name_order_id`(`name`,`order_id`);
單列索引:
ALTER TABLE `test ` ADD KEY `idx_order_id `(`order_id `);
三.索引的結(jié)構(gòu)和原理
3.1磁盤結(jié)構(gòu)以及數(shù)據(jù)存儲

在了解索引結(jié)構(gòu)前,我們先來看下正常情況下我們mysql數(shù)據(jù)庫表中的數(shù)據(jù)是怎么存儲在磁盤中的。
其中磁頭是用于向磁盤讀寫信息的工具咽笼,磁盤上的一圈圈的圓周被稱之為磁道顷编,每圈磁道上的扇形小區(qū)域被稱為扇區(qū)(以下稱之為block),扇區(qū)中又存在著很多存儲單元用于存儲比特信息褐荷。每一個block大小是一樣的,假設(shè)是16384byte;操作系統(tǒng)讀取數(shù)據(jù)都是按照block(也稱之為一頁)為單位進行勾效。磁頭可以旋轉(zhuǎn)伸縮來定位一個block。

磁盤如何存儲數(shù)據(jù)庫數(shù)據(jù):
在上面test表中:
id --> bigint --> 8byte
name --> varchar(20) --> 20byte
code --> varchar(20) --> 20byte
order_id --> varchar(64) --> 64byte
inserttime --> timestamp --> 8byte
updatetime --> timestamp --> 8byte
所以一條數(shù)的大小為128byte;
假設(shè)總共有1000條這樣的數(shù)據(jù),那么存儲這些數(shù)據(jù)需要128 * 1000 / 16384 = 7.8 個block, 假設(shè)當前沒有設(shè)置索引的情況下查詢一條記錄,最多需要查找8個block叛甫。下面來看下索引是如何提高查詢速度的;

索引的數(shù)據(jù)結(jié)構(gòu)
提到數(shù)據(jù)結(jié)構(gòu),就不得不提存儲引擎, 因為在不同的存儲引擎中索引的結(jié)構(gòu)可能是不相同的, 最常見到的存儲引擎有MyISAM 和 InnoDB, 在這兩種存儲引擎中索引的數(shù)據(jù)結(jié)構(gòu)都是B+樹,但在存儲的過程中又稍有不同, 在MyISAM的主鍵索引B+樹的葉子節(jié)點中存儲的是該條數(shù)據(jù)的地址,0x....;而在InnoDB的主鍵索引B+樹的葉子節(jié)點中存儲的是真正的數(shù)據(jù).

MyISAM
從上面我們可以知道數(shù)據(jù)順序的寫在磁盤上, 占用8個block; 現(xiàn)在我們使用id來創(chuàng)建一個索引, 并且還把當前這個id對應(yīng)的數(shù)據(jù)在磁盤中的位置也記錄下來(下面用pointer來描述),這樣test表中的每一行數(shù)據(jù)都會有一條這樣的記錄层宫。

結(jié)構(gòu).png

那在磁盤上存儲這張索引表,需要占據(jù)多少個block呢?
id 8byte
pointer 8byte
所以一條數(shù)據(jù)為16byte,1000條需要使用 16 * 1000 / 16384 = 0.9 個block; 所以在這樣的 情況下查找一條test表中的數(shù)據(jù)最多只需要1次存儲索引數(shù)據(jù)的block數(shù)據(jù)讀入和1次存儲test表數(shù)據(jù)的block數(shù)據(jù)讀入就行了, 相比于沒有索引的情況效率提升了很多

但是在上面的操作中如果數(shù)據(jù)量大的情況還是需要很多次IO,在MyISAM中使用了B+樹的數(shù)據(jù)結(jié)構(gòu),即只有在葉子節(jié)點才存儲行數(shù)據(jù)對應(yīng)的地址(在InnoDB中存儲真正的行數(shù)據(jù)),而非葉子節(jié)點里面的內(nèi)容其實是鍵值和指向數(shù)據(jù)頁的指針其监。

InnoDB
存儲結(jié)構(gòu)下的B+數(shù)大概樣子:

B+.png

下面來算一下一個2層的B+數(shù)能存儲多少數(shù)據(jù),一個block也就是一頁是16384byte, id 8byte, pointer 8byte 總共為16byte,所以第一層最多可存儲16384 / (8 + 8) = 1024條數(shù)據(jù), 所以第二層就對應(yīng)1024個block的首地址, 一個block可以存儲16384 / 128 = 128條數(shù)據(jù), 所以一個2層的B+樹可以存儲1024 * 128 = 131072條數(shù)據(jù),也就是說十幾萬的數(shù)據(jù)量,如果要是查詢的話最多2次IO就可以了;
一個3層的B+樹就可以存儲1024 * 1024 *128條數(shù)據(jù), 可見效率相當之高萌腿。

需要注意的是上面是基于主鍵索引的, 也就是主鍵索引的B+數(shù)中葉子節(jié)點上存儲的是真正的數(shù)據(jù), 而普通索引,如用order_id創(chuàng)建的索引,其葉子節(jié)點上存儲的不是整條的數(shù)據(jù),而是數(shù)據(jù)對應(yīng)的主鍵值, 查詢到主鍵值后再從主鍵的B+數(shù)中獲取到真正的數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抖苦,一起剝皮案震驚了整個濱河市毁菱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锌历,老刑警劉巖贮庞,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異究西,居然都是意外死亡窗慎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門卤材,熙熙樓的掌柜王于貴愁眉苦臉地迎上來遮斥,“玉大人,你說我怎么就攤上這事扇丛∈趼穑” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵帆精,是天一觀的道長较屿。 經(jīng)常有香客問我,道長卓练,這世上最難降的妖魔是什么隘蝎? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮昆庇,結(jié)果婚禮上末贾,老公的妹妹穿的比我還像新娘。我一直安慰自己整吆,他們只是感情好拱撵,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著表蝙,像睡著了一般拴测。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上府蛇,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天集索,我揣著相機與錄音,去河邊找鬼。 笑死务荆,一個胖子當著我的面吹牛妆距,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播函匕,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼娱据,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了盅惜?” 一聲冷哼從身側(cè)響起中剩,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抒寂,沒想到半個月后结啼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡屈芜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年郊愧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沸伏。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡糕珊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毅糟,到底是詐尸還是另有隱情红选,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布姆另,位于F島的核電站喇肋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏迹辐。R本人自食惡果不足惜蝶防,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望明吩。 院中可真熱鬧间学,春花似錦、人聲如沸印荔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仍律。三九已至嘿悬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間水泉,已是汗流浹背善涨。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工窒盐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人钢拧。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓蟹漓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親娶靡。 傳聞我的和親對象是個殘疾皇子牧牢,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

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