1. 程式人生 > 其它 >MySQL索引建立及使用

MySQL索引建立及使用

轉自:https://blog.csdn.net/dengchenrong/article/details/88425762

背景

最近在深化學習資料庫相關知識,藉此機會總結記錄一番,本來想自己總結概括一下,但是看到一篇寫的簡潔明瞭的部落格,為節約時間就直接搬運過來了,有些地方加入一些自己的見解。
https://blog.csdn.net/xluren/article/details/32746183

關於MySQL索引的好處,如果正確合理設計並且使用索引的MySQL是一輛蘭博基尼的話,那麼沒有設計和使用索引的MySQL就是一個人力三輪車。對於沒有索引的表,單表查詢可能幾十萬資料就是瓶頸,而通常大型網站單日就可能會產生幾十萬甚至幾百萬的資料,沒有索引查詢會變的非常緩慢。還是以WordPress來說,其多個數據表都會對經常被查詢的欄位新增索引,比如wp_comments表中針對5個欄位設計了BTREE索引。

一、簡單的對比測試

以我去年測試的資料作為一個簡單示例,20多條資料來源隨機生成200萬條資料,平均每條資料來源都重複大概10萬次,表結構比較簡單,僅包含一個自增ID,一個char型別,一個text型別和一個int型別,單表2G大小,使用MyIASM引擎。開始測試未新增任何索引。

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

查詢需要的時間非常恐怖的,如果加上聯合查詢和其他一些約束條件,資料庫會瘋狂的消耗記憶體,並且會影響前端程式的執行。這時給title欄位新增一個BTREE索引:

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

給title欄位加上索引後,查詢速度是立竿見影。

二、MySQL索引的概念

索引是一種特殊的檔案(InnoDB資料表上的索引是表空間的一個組成部分),它們包含著對資料表裡所有記錄的引用指標。更通俗的說,資料庫索引好比是一本書前面的目錄能加快資料庫的查詢速度。上述SQL語句,在沒有索引的情況下,資料庫會遍歷全部200條資料後選擇符合條件的;而有了相應的索引之後,資料庫會直接在索引中查詢符合條件的選項。如果我們把SQL語句換成“SELECT * FROM article WHERE id=2000000”,那麼你是希望資料庫按照順序讀取完200萬行資料以後給你結果還是直接在索引中定位呢?(注:一般資料庫預設都會為主鍵生成索引)。

索引分為聚簇索引和非聚簇索引兩種,聚簇索引是按照資料存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對於單行的檢索很快。

三、索引的型別

1、普通索引
這是最基本的索引,它沒有任何限制,比如上文中為title欄位建立的索引就是一個普通索引,MyIASM中預設的BTREE型別的索引,也是我們大多數情況下用到的索引。
建立方式:

  • 直接建立索引
CREATE INDEX index_name ON table(column(length))
  • 修改表結構的方式新增索引
ALTER TABLE table_name ADD INDEX index_name ON (column(length))
  • 建立表的時候同時建立索引
CREATE TABLE `table` (
	`id` int(11) NOT NULL AUTO_INCREMENT ,
	`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
	`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
	`time` int(10) NULL DEFAULT NULL ,
	PRIMARY KEY (`id`),
	INDEX index_name (title(length))
)

  • 刪除索引
DROP INDEX index_name ON table

2、唯一索引
與普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須是唯一的,建立方法和普通索引類似。

  • 建立唯一索引
CREATE UNIQUE INDEX index_name ON table(column(length))

  • 修改表結構
ALTER TABLE table_name ADD UNIQUE INDEX index_name ON (column(length))

  • 建立表時同時建立索引
CREATE TABLE `table` (
	`id` int(11) NOT NULL AUTO_INCREMENT ,
	`title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
	`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,
	`time` int(10) NULL DEFAULT NULL ,
	PRIMARY KEY (`id`),
	UNIQUE indexName (title(length))
);

3、組合索引
平時用的SQL查詢
語句一般都有比較多的限制條件,所以為了進一步榨取MySQL的效率,就要考慮建立組合索引。例如上表中針對title和time建立一個組合索引:

ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))

建立這樣的組合索引,其實是相當於分別建立了下面兩組組合索引:

–title,time

–title

為什麼沒有time這樣的組合索引呢?這是因為MySQL組合索引最左字首”的結果。
簡單的理解就是隻從最左面的開始組合。並不是只要包含這兩列的查詢都會用到該組合索引,如下面的幾個SQL所示:

  • 使用到上面的索引
SELECT * FROM article WHREE title='測試' AND time=1234567890;

SELECT * FROM article WHREE utitle='測試';

  • 未使用到上面的索引
SELECT * FROM article WHREE time=1234567890;

以上就是常用的三種索引型別及其建立使用的方法,當然還有其他的型別,這裡我就列舉我們平時最常用的幾種,更詳細和全面的索引相關資料請諮詢度娘。

總結:
常用的索引型別
1、普通索引
2、唯一索引
3、組合索引

普通索引和唯一索引的建立方式有三種,分別是直接建立、修改表結構建立、建立表時同時建立,注意組合索引的組合規則是最左字首索引

四、索引的優化

上面說了使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要儲存資料,還要儲存一下索引檔案。建立索引會佔用磁碟空間的索引檔案。一般情況這個問題不太嚴重,但如果你在一個大表上建立了多種組合索引,索引檔案的會膨脹很快。索引只是提高效率的一個因素,如果你的MySQL有大資料量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。下面是一些總結以及收藏的MySQL索引的注意事項和優化方法。

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

事實上,我們可以通過前面聚集索引和非聚集索引的定義的例子來理解上表。如:返回某範圍內的資料一項。比如您的某個表有一個時間列,恰好您把聚合索引建立在了該列,這時您查詢2004年1月1日至2004年10月1日之間的全部資料時,這個速度就將是很快的,因為您的這本字典正文是按日期進行排序的,聚類索引只需要找到要檢索的所有資料中的開頭和結尾資料即可;而不像非聚集索引,必須先查到目錄中查到每一項資料對應的頁碼,然後再根據頁碼查到具體內容。

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

只要列中包含有NULL值都將不會被包含在索引中,複合索引中只要有一列含有NULL值,那麼這一列對於此複合索引就是無效的。所以我們在資料庫設計時不要讓欄位的預設值為NULL。

3. 使用短索引

對串列進行索引,如果可能應該指定一個字首長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字元內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁碟空間和I/O操作。

4. 索引列排序

MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。因此資料庫預設排序可以符合要求的情況下不要使用排序操作;儘量不要包含多個列的排序,如果需要最好給這些列建立複合索引。

5. like語句操作

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

6. 不要在列上進行運算

例如:select * from users where YEAR(adddate)<2007,將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成:select * from users where adddate<’2007-01-01′。關於這一點可以圍觀:一個單引號引發的MYSQL效能損失。

最後總結一下,MySQL只對以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like(不以萬用字元%或_開頭的情形)。
而理論上每張表裡面最多可建立16個索引,不過除非是資料量真的很多,否則過多的使用索引會引起反作用,索引雖好用,可不要太迷戀噢。