mysql索引總結(jié)----mysql 索引類型以及創(chuàng)建(轉(zhuǎn)載)

文章歸屬:MySQL索引使用方法和性能優(yōu)化冒签,此君總結(jié)的非常詳細挤巡。直接搬過來了系瓢。
轉(zhuǎn)載時間:21017 11 08

關(guān)于MySQL索引的好處召廷,如果正確合理設(shè)計并且使用索引的MySQL是一輛蘭博基尼的話,那么沒有設(shè)計和使用索引的MySQL就是一個人力三輪車雾叭。對于沒有索引的表悟耘,單表查詢可能幾十萬數(shù)據(jù)就是瓶頸,而通常大型網(wǎng)站單日就可能會產(chǎn)生幾十萬甚至幾百萬的數(shù)據(jù)拷况,沒有索引查詢會變的非常緩慢作煌。還是以WordPress來說,其多個數(shù)據(jù)表都會對經(jīng)常被查詢的字段添加索引赚瘦,比如wp_comments表中針對5個字段設(shè)計了BTREE索引粟誓。

一個簡單的對比測試

以我去年測試的數(shù)據(jù)作為一個簡單示例,20多條數(shù)據(jù)源隨機生成200萬條數(shù)據(jù)起意,平均每條數(shù)據(jù)源都重復(fù)大概10萬次鹰服,表結(jié)構(gòu)比較簡單,僅包含一個自增ID,一個char類型悲酷,一個text類型和一個int類型套菜,單表2G大小,使用MyIASM引擎设易。開始測試未添加任何索引逗柴。

執(zhí)行下面的SQL語句:

mysql> SELECT id,FROM_UNIXTIME(time) FROM article WHERE a.title='測試標(biāo)題'

查詢需要的時間非常恐怖的顿肺,如果加上聯(lián)合查詢和其他一些約束條件戏溺,數(shù)據(jù)庫會瘋狂的消耗內(nèi)存,并且會影響前端程序的執(zhí)行屠尊。這時給title字段添加一個BTREE索引:

mysql> ALTER TABLE article ADD INDEX index_article_title ON title(200);

再次執(zhí)行上述查詢語句旷祸,其對比非常明顯:

MySQL索引的概念

索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個組成部分),它們包含著對數(shù)據(jù)表里所有記錄的引用指針讼昆。更通俗的說托享,數(shù)據(jù)庫索引好比是一本書前面的目錄,能加快數(shù)據(jù)庫的查詢速度浸赫。上述SQL語句闰围,在沒有索引的情況下,數(shù)據(jù)庫會遍歷全部200條數(shù)據(jù)后選擇符合條件的既峡;而有了相應(yīng)的索引之后辫诅,數(shù)據(jù)庫會直接在索引中查找符合條件的選項。如果我們把SQL語句換成“SELECT * FROM article WHERE id=2000000”涧狮,那么你是希望數(shù)據(jù)庫按照順序讀取完200萬行數(shù)據(jù)以后給你結(jié)果還是直接在索引中定位呢?上面的兩個圖片鮮明的用時對比已經(jīng)給出了答案(注:一般數(shù)據(jù)庫默認都會為主鍵生成索引)么夫。

索引分為聚簇索引和非聚簇索引兩種者冤,聚簇索引是按照數(shù)據(jù)存放的物理位置為順序的,而非聚簇索引就不一樣了档痪;聚簇索引能提高多行檢索的速度涉枫,而非聚簇索引對于單行的檢索很快。

MySQL索引的類型

1. 普通索引

這是最基本的索引腐螟,它沒有任何限制愿汰,比如上文中為title字段創(chuàng)建的索引就是一個普通索引,MyIASM中默認的BTREE類型的索引乐纸,也是我們大多數(shù)情況下用到的索引衬廷。

01  –直接創(chuàng)建索引
02  CREATE INDEX index_name ON table(column(length))

03  –修改表結(jié)構(gòu)的方式添加索引
04  ALTER TABLE table_name ADD INDEX index_name ON (column(length))

05  –創(chuàng)建表的時候同時創(chuàng)建索引
06  CREATE TABLE `table` (
07      `id` int(11) NOT NULL AUTO_INCREMENT ,
08      `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
09      `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
10      `time` int(10) NULL DEFAULT NULL ,
11       PRIMARY KEY (`id`),
12       INDEX index_name (title(length))
13  )

14  –刪除索引
15  DROP INDEX index_name ON table

2. 唯一索引

與普通索引類似,不同的就是:索引列的值必須唯一汽绢,但允許有空值(注意和主鍵不同)吗跋。如果是組合索引,則列值的組合必須唯一,創(chuàng)建方法和普通索引類似跌宛。

01  –創(chuàng)建唯一索引
02  CREATE UNIQUE INDEX indexName ON table(column(length))

03  –修改表結(jié)構(gòu)
04  ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))

05  –創(chuàng)建表的時候直接指定
06  CREATE TABLE `table` (
07      `id` int(11) NOT NULL AUTO_INCREMENT ,
08      `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
09      `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
10      `time` int(10) NULL DEFAULT NULL ,
11      PRIMARY KEY (`id`),
12      UNIQUE indexName (title(length))
13  );

3. 全文索引(FULLTEXT)

MySQL從3.23.23版開始支持全文索引和全文檢索酗宋,F(xiàn)ULLTEXT索引僅可用于 MyISAM 表;他們可以從CHAR疆拘、VARCHAR或TEXT列中作為CREATE TABLE語句的一部分被創(chuàng)建蜕猫,或是隨后使用ALTER TABLE 或CREATE INDEX被添加。////對于較大的數(shù)據(jù)集哎迄,將你的資料輸入一個沒有FULLTEXT索引的表中回右,然后創(chuàng)建索引,其速度比把資料輸入現(xiàn)有FULLTEXT索引的速度更為快芬失。不過切記對于大容量的數(shù)據(jù)表楣黍,生成全文索引是一個非常消耗時間非常消耗硬盤空間的做法。

01  –創(chuàng)建表的適合添加全文索引
02  CREATE TABLE `table` (
03    `id` int(11) NOT NULL AUTO_INCREMENT ,
04    `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
05    `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
06    `time` int(10) NULL DEFAULT NULL ,
07    PRIMARY KEY (`id`),
08    FULLTEXT (content)
09  );

10  –修改表結(jié)構(gòu)添加全文索引
11  ALTER TABLE article ADD FULLTEXT index_content(content)

12  –直接創(chuàng)建索引
13  CREATE FULLTEXT INDEX index_content ON article(content)

4. 單列索引棱烂、多列索引

多個單列索引與單個多列索引的查詢效果不同租漂,因為執(zhí)行查詢時,MySQL只能使用一個索引颊糜,會從多個索引中選擇一個限制最為嚴格的索引哩治。

5. 組合索引(最左前綴)

平時用的SQL查詢語句一般都有比較多的限制條件,所以為了進一步榨取MySQL的效率衬鱼,就要考慮建立組合索引业筏。例如上表中針對title和time建立一個組合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立這樣的組合索引鸟赫,其實是相當(dāng)于分別建立了下面兩組組合索引:

–title,time
–title

為什么沒有time這樣的組合索引呢蒜胖?這是因為MySQL組合索引“最左前綴”的結(jié)果。簡單的理解就是只從最左面的開始組合抛蚤。并不是只要包含這兩列的查詢都會用到該組合索引台谢,如下面的幾個SQL所示:

1   –使用到上面的索引
2   SELECT * FROM article WHREE title='測試' AND time=1234567890;
3   SELECT * FROM article WHREE utitle='測試';

4   –不使用上面的索引
5   SELECT * FROM article WHREE time=1234567890;

MySQL索引的優(yōu)化

上面都在說使用索引的好處,但過多的使用索引將會造成濫用岁经。因此索引也會有它的缺點:雖然索引大大提高了查詢速度朋沮,同時卻會降低更新表的速度,如對表進行INSERT缀壤、UPDATE和DELETE樊拓。因為更新表時,MySQL不僅要保存數(shù)據(jù)塘慕,還要保存一下索引文件筋夏。建立索引會占用磁盤空間的索引文件。一般情況這個問題不太嚴重图呢,但如果你在一個大表上創(chuàng)建了多種組合索引叁丧,索引文件的會膨脹很快。索引只是提高效率的一個因素,如果你的MySQL有大數(shù)據(jù)量的表拥娄,就需要花時間研究建立最優(yōu)秀的索引蚊锹,或優(yōu)化查詢語句。下面是一些總結(jié)以及收藏的MySQL索引的注意事項和優(yōu)化方法稚瘾。

1. 何時使用聚集索引或非聚集索引牡昆?

動作描述 使用聚集索引 使用非聚集索引
列經(jīng)常被分組排序 使用 使用
返回某范圍內(nèi)的數(shù)據(jù) 使用 不使用
一個或極少不同值 不使用 不使用
小數(shù)目的不同值 使用 不使用
大數(shù)目的不同值 不使用 使用
頻繁更新的列 不使用 使用
外鍵列 使用 使用
主鍵列 使用 使用
頻繁修改索引列 不使用 使用

事實上,我們可以通過前面聚集索引和非聚集索引的定義的例子來理解上表摊欠。如:返回某范圍內(nèi)的數(shù)據(jù)一項丢烘。比如您的某個表有一個時間列,恰好您把聚合索引建立在了該列些椒,這時您查詢2004年1月1日至2004年10月1日之間的全部數(shù)據(jù)時播瞳,這個速度就將是很快的,因為您的這本字典正文是按日期進行排序的免糕,聚類索引只需要找到要檢索的所有數(shù)據(jù)中的開頭和結(jié)尾數(shù)據(jù)即可赢乓;而不像非聚集索引,必須先查到目錄中查到每一項數(shù)據(jù)對應(yīng)的頁碼石窑,然后再根據(jù)頁碼查到具體內(nèi)容牌芋。其實這個具體用法我還不是很理解,只能等待后期的項目開發(fā)中慢慢學(xué)學(xué)了松逊。

2. 索引不會包含有NULL值的列

只要列中包含有NULL值都將不會被包含在索引中躺屁,復(fù)合索引中只要有一列含有NULL值,那么這一列對于此復(fù)合索引就是無效的经宏。所以我們在數(shù)據(jù)庫設(shè)計時不要讓字段的默認值為NULL犀暑。

3. 使用短索引

對串列進行索引,如果可能應(yīng)該指定一個前綴長度烁兰。例如母怜,如果有一個CHAR(255)的列,如果在前10個或20個字符內(nèi)缚柏,多數(shù)值是惟一的,那么就不要對整個列進行索引碟贾。短索引不僅可以提高查詢速度而且可以節(jié)省磁盤空間和I/O操作币喧。

4. 索引列排序

MySQL查詢只使用一個索引,因此如果where子句中已經(jīng)使用了索引的話袱耽,那么order by中的列是不會使用索引的杀餐。因此數(shù)據(jù)庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序朱巨,如果需要最好給這些列創(chuàng)建復(fù)合索引史翘。

5. like語句操作

一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題琼讽。like “%aaa%” 不會使用索引而like “aaa%”可以使用索引必峰。

6. 不要在列上進行運算

例如:select * from users where YEAR(adddate)<2007,將在每個行上進行運算钻蹬,這將導(dǎo)致索引失效而進行全表掃描吼蚁,因此我們可以改成:select * from users where adddate<’2007-01-01′。關(guān)于這一點可以圍觀:一個單引號引發(fā)的MYSQL性能損失问欠。

最后總結(jié)一下肝匆,MySQL只對一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like(不以通配符%或_開頭的情形)。而理論上每張表里面最多可創(chuàng)建16個索引顺献,不過除非是數(shù)據(jù)量真的很多旗国,否則過多的使用索引也不是那么好玩的,比如我剛才針對text類型的字段創(chuàng)建索引的時候注整,系統(tǒng)差點就卡死了能曾。


                                   20171108
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市设捐,隨后出現(xiàn)的幾起案子借浊,更是在濱河造成了極大的恐慌,老刑警劉巖萝招,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚂斤,死亡現(xiàn)場離奇詭異,居然都是意外死亡槐沼,警方通過查閱死者的電腦和手機曙蒸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岗钩,“玉大人纽窟,你說我怎么就攤上這事〖嫦牛” “怎么了臂港?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長视搏。 經(jīng)常有香客問我审孽,道長,這世上最難降的妖魔是什么浑娜? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任佑力,我火速辦了婚禮,結(jié)果婚禮上筋遭,老公的妹妹穿的比我還像新娘打颤。我一直安慰自己暴拄,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布编饺。 她就那樣靜靜地躺著乖篷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪反肋。 梳的紋絲不亂的頭發(fā)上那伐,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音石蔗,去河邊找鬼罕邀。 笑死,一個胖子當(dāng)著我的面吹牛养距,可吹牛的內(nèi)容都是我干的诉探。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼棍厌,長吁一口氣:“原來是場噩夢啊……” “哼肾胯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耘纱,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤敬肚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后束析,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艳馒,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年员寇,在試婚紗的時候發(fā)現(xiàn)自己被綠了弄慰。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蝶锋,死狀恐怖陆爽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扳缕,我是刑警寧澤慌闭,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站躯舔,受9級特大地震影響驴剔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庸毫,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衫樊。 院中可真熱鬧飒赃,春花似錦利花、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蔫慧,卻和暖如春挠乳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姑躲。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工睡扬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人黍析。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓卖怜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阐枣。 傳聞我的和親對象是個殘疾皇子马靠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

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