- 相關(guān)推薦
數(shù)據(jù)庫(kù)索引的使用方法
走向精通MySQL的道路非常的艱難,還好各種關(guān)系型數(shù)據(jù)庫(kù)大同小異,足夠讓我從增刪改查上升到高性能數(shù)據(jù)庫(kù)的架構(gòu)和調(diào)優(yōu)。這期間的各種概念就不絮叨了,我也很難表述的很清楚,昨天寫了個(gè)小腳本往我本機(jī)MySQL數(shù)據(jù)庫(kù)的某張表里面注入了200萬(wàn)條數(shù)據(jù)(Windows7旗艦版/1.66GHz/2G內(nèi)存/MySQL5.1.50),數(shù)據(jù)表的結(jié)構(gòu)如下圖所示,屬于一個(gè)比較基本的定長(zhǎng)表,考慮到我可憐的本本的承受能力,id使用從1開始的自增,title字段為隨機(jī)20個(gè)標(biāo)題中的一個(gè),content都是相同的內(nèi)容,time使用時(shí)間戳而非datetime類型,即10位整型數(shù)據(jù)。
就是這么一個(gè)結(jié)構(gòu)極其簡(jiǎn)單的表,200萬(wàn)數(shù)量級(jí)的復(fù)雜查詢將會(huì)變的非常緩慢,比如執(zhí)行下面的SQL語(yǔ)句。
SELECT a.id,FROM_UNIXTIME(a.time)
FROM article AS a
WHERE a.title=‘PHP筆試題和答案——基礎(chǔ)語(yǔ)言方面’
查詢時(shí)間基本上需要50-100秒,這個(gè)是非?植赖模绻由下(lián)合查詢和其他一些約束條件,數(shù)據(jù)庫(kù)會(huì)瘋狂的消耗內(nèi)存。
如果這時(shí)候數(shù)據(jù)庫(kù)里面針對(duì)title字段建立了索引,查詢效率將會(huì)大幅度提升,如下圖所示?梢妼(duì)于大型數(shù)據(jù)庫(kù),建立索引是非常非常重要的一個(gè)優(yōu)化手段(當(dāng)然還會(huì)有很多其他優(yōu)化這樣的數(shù)據(jù)庫(kù)的方法,但是本文主題所限,暫不討論。),廢話了這么多,以下開始總結(jié)MySQL中索引的使用方法和性能優(yōu)化以及一些注意事項(xiàng)。
索引的概念
索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個(gè)組成部分),它們包含著對(duì)數(shù)據(jù)表里所有記錄的引用指針。更通俗的說,數(shù)據(jù)庫(kù)索引好比是一本書前面的目錄,能加快數(shù)據(jù)庫(kù)的查詢速度。上述SQL語(yǔ)句,在沒有索引的情況下,數(shù)據(jù)庫(kù)會(huì)遍歷全部200條數(shù)據(jù)后選擇符合條件的;而有了相應(yīng)的索引之后,數(shù)據(jù)庫(kù)會(huì)直接在索引中查找符合條件的選項(xiàng)。如果我們把SQL語(yǔ)句換成“SELECT * FROM article WHERE id=2000000”,那么你是希望數(shù)據(jù)庫(kù)按照順序讀取完200萬(wàn)行數(shù)據(jù)以后給你結(jié)果還是直接在索引中定位呢?上面的兩個(gè)圖片鮮明的用時(shí)對(duì)比已經(jīng)給出了答案(注:一般數(shù)據(jù)庫(kù)默認(rèn)都會(huì)為主鍵生成索引)。
索引分為聚簇索引和非聚簇索引兩種,聚簇索引是按照數(shù)據(jù)存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對(duì)于單行的檢索很快。
索引的類型
1. 普通索引
這是最基本的索引,它沒有任何限制,比如上文中為title字段創(chuàng)建的索引就是一個(gè)普通索引。
–直接創(chuàng)建索引
CREATE INDEX indexName ON table(column(length))
–修改表結(jié)構(gòu)的方式添加索引
ALTER tableADD INDEX indexName ON (column(length))
–創(chuàng)建表的時(shí)候同時(shí)創(chuàng)建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` 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 indexName (title(length))
)
–刪除索引
DROP INDEX indexName ON table
2. 唯一索引
與普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值(注意和主鍵不同)。如果是組合索引,則列值的組合必須唯一,創(chuàng)建方法和普通索引類似。
–創(chuàng)建唯一索引
CREATE UNIQUE INDEX indexName ON table(column(length))
–修改表結(jié)構(gòu)
ALTER table ADD UNIQUE indexName ON (column(length))
–創(chuàng)建表的時(shí)候直接指定
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` 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. 全文索引(FULLTEXT)
MySQL從3.23.23版開始支持全文索引和全文檢索,F(xiàn)ULLTEXT索引僅可用于 MyISAM 表;他們可以從CHAR、VARCHAR或TEXT列中作為CREATE TABLE語(yǔ)句的一部分被創(chuàng)建,或是隨后使用ALTER TABLE 或CREATE INDEX被添加。////對(duì)于較大的數(shù)據(jù)集,將你的資料輸入一個(gè)沒有FULLTEXT索引的表中,然后創(chuàng)建索引,其速度比把資料輸入現(xiàn)有FULLTEXT索引的速度更為快。不過切記對(duì)于大容量的數(shù)據(jù)表,生成全文索引是一個(gè)非常消耗時(shí)間非常消耗硬盤空間的做法。
–創(chuàng)建表的適合添加全文索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` 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`),
FULLTEXT (content)
);
–修改表結(jié)構(gòu)添加全文索引
ALTER TABLE article ADD FULLTEXT index_content(content)
–直接創(chuàng)建索引
CREATE FULLTEXT INDEX index_content ON article(content)
4. 單列索引、多列索引
多個(gè)單列索引與單個(gè)多列索引的查詢效果不同,因?yàn)閳?zhí)行查詢時(shí),MySQL只能使用一個(gè)索引,會(huì)從多個(gè)索引中選擇一個(gè)限制最為嚴(yán)格的索引。
5. 組合索引(最左前綴)
平時(shí)用的SQL查詢語(yǔ)句一般都有比較多的限制條件,所以為了進(jìn)一步榨取MySQL的效率,就要考慮建立組合索引。例如上表中針對(duì)title和time建立一個(gè)組合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立這樣的組合索引,其實(shí)是相當(dāng)于分別建立了下面兩組組合索引:
–title,time
–title
為什么沒有time這樣的組合索引呢?這是因?yàn)镸ySQL組合索引“最左前綴”的結(jié)果。簡(jiǎn)單的理解就是只從最左面的開始組合。并不是只要包含這兩列的查詢都會(huì)用到該組合索引,如下面的幾個(gè)SQL所示:
–使用到上面的索引
SELECT * FROM article WHREE title=“PHP程序員” AND time=1234567890
SELECT * FROM article WHREE utitle=“PHP程序員”
–不使用上面的索引
SELECT * FROM article WHREE time=1234567890
MySQL索引的優(yōu)化
上面都在說使用索引的好處,但過多的使用索引將會(huì)造成濫用。因此索引也會(huì)有它的缺點(diǎn):雖然索引大大提高了查詢速度,同時(shí)卻會(huì)降低更新表的速度,如對(duì)表進(jìn)行INSERT、UPDATE和DELETE。因?yàn)楦卤頃r(shí),MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件。建立索引會(huì)占用磁盤空間的索引文件。一般情況這個(gè)問題不太嚴(yán)重,但如果你在一個(gè)大表上創(chuàng)建了多種組合索引,索引文件的會(huì)膨脹很快。索引只是提高效率的一個(gè)因素,如果你的MySQL有大數(shù)據(jù)量的表,就需要花時(shí)間研究建立最優(yōu)秀的索引,或優(yōu)化查詢語(yǔ)句。下面是一些總結(jié)以及收藏的MySQL索引的注意事項(xiàng)和優(yōu)化方法。
1. 何時(shí)使用聚集索引或非聚集索引?
動(dòng)作描述 使用聚集索引 使用非聚集索引 列經(jīng)常被分組排序 使用 使用 返回某范圍內(nèi)的數(shù)據(jù) 使用 不使用 一個(gè)或極少不同值 不使用 不使用 小數(shù)目的不同值 使用 不使用 大數(shù)目的不同值 不使用 使用 頻繁更新的列 不使用 使用 外鍵列 使用 使用 主鍵列 使用 使用 頻繁修改索引列 不使用 使用
事實(shí)上,我們可以通過前面聚集索引和非聚集索引的定義的例子來(lái)理解上表。如:返回某范圍內(nèi)的數(shù)據(jù)一項(xiàng)。比如您的某個(gè)表有一個(gè)時(shí)間列,恰好您把聚合索引建立在了該列,這時(shí)您查詢2004年1月1日至2004年10月1日之間的全部數(shù)據(jù)時(shí),這個(gè)速度就將是很快的,因?yàn)槟倪@本字典正文是按日期進(jìn)行排序的,聚類索引只需要找到要檢索的所有數(shù)據(jù)中的開頭和結(jié)尾數(shù)據(jù)即可;而不像非聚集索引,必須先查到目錄中查到每一項(xiàng)數(shù)據(jù)對(duì)應(yīng)的頁(yè)碼,然后再根據(jù)頁(yè)碼查到具體內(nèi)容。其實(shí)這個(gè)具體用法我還不是很理解,只能等待后期的項(xiàng)目開發(fā)中慢慢學(xué)學(xué)了。
2. 索引不會(huì)包含有NULL值的列
只要列中包含有NULL值都將不會(huì)被包含在索引中,復(fù)合索引中只要有一列含有NULL值,那么這一列對(duì)于此復(fù)合索引就是無(wú)效的。所以我們?cè)跀?shù)據(jù)庫(kù)設(shè)計(jì)時(shí)不要讓字段的默認(rèn)值為NULL。
3. 使用短索引
對(duì)串列進(jìn)行索引,如果可能應(yīng)該指定一個(gè)前綴長(zhǎng)度。例如,如果有一個(gè)CHAR(255)的列,如果在前10個(gè)或20個(gè)字符內(nèi),多數(shù)值是惟一的,那么就不要對(duì)整個(gè)列進(jìn)行索引。短索引不僅可以提高查詢速度而且可以節(jié)省磁盤空間和I/O操作。
4. 索引列排序
MySQL查詢只使用一個(gè)索引,因此如果where子句中已經(jīng)使用了索引的話,那么order by中的列是不會(huì)使用索引的。因此數(shù)據(jù)庫(kù)默認(rèn)排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個(gè)列的排序,如果需要最好給這些列創(chuàng)建復(fù)合索引。
5. like語(yǔ)句操作
一般情況下不鼓勵(lì)使用like操作,如果非使用不可,如何使用也是一個(gè)問題。like “%aaa%” 不會(huì)使用索引而like “aaa%”可以使用索引。
6. 不要在列上進(jìn)行運(yùn)算
例如:select * from users where YEAR(adddate)<2007,將在每個(gè)行上進(jìn)行運(yùn)算,這將導(dǎo)致索引失效而進(jìn)行全表掃描,因此我們可以改成:select * from users where adddate<’2007-01-01′。關(guān)于這一點(diǎn)可以圍觀:一個(gè)單引號(hào)引發(fā)的MYSQL性能損失。
最后總結(jié)一下,MySQL只對(duì)一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時(shí)候的like(不以通配符%或_開頭的情形)。而理論上每張表里面最多可創(chuàng)建16個(gè)索引,不過除非是數(shù)據(jù)量真的很多,否則過多的使用索引也不是那么好玩的,比如我剛才針對(duì)text類型的字段創(chuàng)建索引的時(shí)候,系統(tǒng)差點(diǎn)就卡死了。
最后的最后PS:現(xiàn)在更新個(gè)技術(shù)文章真難,還得做大量實(shí)驗(yàn)…
【數(shù)據(jù)庫(kù)索引的使用方法】相關(guān)文章:
搜索引擎的深度分析07-14
搜索引擎網(wǎng)站質(zhì)量評(píng)級(jí)07-14
潤(rùn)發(fā)乳使用方法與護(hù)發(fā)素使用方法08-04
護(hù)膝的使用方法07-27
護(hù)具的使用方法02-07
腳注使用方法11-11
數(shù)據(jù)庫(kù)設(shè)計(jì)08-06