引用:http://blog.csdn.net/xluren/article/details/32746183
http://www.zendstudio.net/archives/single-quotes-or-no-single-quotes-in-sql-query/
要點:
- MySQL只對一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like(不以通配符%或_開頭的情形)。而理論上每張表里面最多可創(chuàng)建16個索引产场,不過除非是數(shù)據(jù)量真的很多鹅髓,否則過多的使用索引也不是那么好玩的.
- 一般數(shù)據(jù)庫默認都會為主鍵生成索引
關(guān)于MySQL索引的好處,如果正確合理設(shè)計并且使用索引的MySQL是一輛蘭博基尼的話京景,那么沒有設(shè)計和使用索引的MySQL就是一個人力三輪車窿冯。對于沒有索引的表,單表查詢可能幾十萬數(shù)據(jù)就是瓶頸确徙,而通常大型網(wǎng)站單日就可能會產(chǎn)生幾十萬甚至幾百萬的數(shù)據(jù)醒串,沒有索引查詢會變的非常緩慢。
一個簡單的對比測試
以我去年測試的數(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='測試標題'
查詢需要的時間非尘执恐怖的绰姻,如果加上聯(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ù)情況下用到的索引癌椿。
2. 唯一索引
與普通索引類似,不同的就是:索引列的值必須唯一菱阵,但允許有空值(注意和主鍵不同)踢俄。如果是組合索引,則列值的組合必須唯一晴及,創(chuàng)建方法和普通索引類似褪贵。
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ù)表,生成全文索引是一個非常消耗時間非常消耗硬盤空間的做法茸塞。
4. 單列索引躲庄、多列索引
多個單列索引與單個多列索引的查詢效果不同,因為執(zhí)行查詢時钾虐,MySQL只能使用一個索引噪窘,會從多個索引中選擇一個限制最為嚴格的索引。
5. 組合索引(最左前綴)
平時用的SQL查詢語句一般都有比較多的限制條件效扫,所以為了進一步榨取MySQL的效率倔监,就要考慮建立組合索引。例如上表中針對title和time建立一個組合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))菌仁。建立這樣的組合索引浩习,其實是相當于分別建立了下面兩組組合索引:
–title,time
–title
為什么沒有time這樣的組合索引呢?這是因為MySQL組合索引“最左前綴”的結(jié)果济丘。簡單的理解就是只從最左面的開始組合谱秽。并不是只要包含這兩列的查詢都會用到該組合索引,如下面的幾個SQL所示:
MySQL索引的優(yōu)化
上面都在說使用索引的好處,但過多的使用索引將會造成濫用疟赊。
因此索引也會有它的缺點:雖然索引大大提高了查詢速度辱士,同時卻會降低更新表的速度,如對表進行INSERT听绳、UPDATE和DELETE颂碘。
因為更新表時,MySQL不僅要保存數(shù)據(jù)椅挣,還要保存一下索引文件头岔。
建立索引會占用磁盤空間的索引文件。
一般情況這個問題不太嚴重鼠证,但如果你在一個大表上創(chuàng)建了多種組合索引峡竣,索引文件的會膨脹很快。
索引只是提高效率的一個因素量九,如果你的MySQL有大數(shù)據(jù)量的表适掰,就需要花時間研究建立最優(yōu)秀的索引,或優(yōu)化查詢語句荠列。
下面是一些總結(jié)以及收藏的MySQL索引的注意事項和優(yōu)化方法:
-
何時使用聚集索引或非聚集索引类浪?
Paste_Image.png
事實上,我們可以通過前面聚集索引和非聚集索引的定義的例子來理解上表肌似。如:返回某范圍內(nèi)的數(shù)據(jù)一項费就。比如您的某個表有一個時間列,恰好您把聚合索引建立在了該列川队,這時您查詢2004年1月1日至2004年10月1日之間的全部數(shù)據(jù)時力细,這個速度就將是很快的,因為您的這本字典正文是按日期進行排序的固额,聚類索引只需要找到要檢索的所有數(shù)據(jù)中的開頭和結(jié)尾數(shù)據(jù)即可眠蚂;而不像非聚集索引,必須先查到目錄中查到每一項數(shù)據(jù)對應(yīng)的頁碼斗躏,然后再根據(jù)頁碼查到具體內(nèi)容逝慧。
- 索引不會包含有NULL值的列
只要列中包含有NULL值都將不會被包含在索引中,復(fù)合索引中只要有一列含有NULL值瑟捣,那么這一列對于此復(fù)合索引就是無效的馋艺。所以我們在數(shù)據(jù)庫設(shè)計時不要讓字段的默認值為NULL。 - 使用短索引
對串列進行索引迈套,如果可能應(yīng)該指定一個前綴長度。例如碱鳞,如果有一個CHAR(255)的列桑李,如果在前10個或20個字符內(nèi),多數(shù)值是惟一的,那么就不要對整個列進行索引贵白。短索引不僅可以提高查詢速度而且可以節(jié)省磁盤空間和I/O操作率拒。 - 索引列排序
MySQL查詢只使用一個索引,因此如果where子句中已經(jīng)使用了索引的話禁荒,那么order by中的列是不會使用索引的猬膨。因此數(shù)據(jù)庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序呛伴,如果需要最好給這些列創(chuàng)建復(fù)合索引勃痴。 - like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可热康,如何使用也是一個問題沛申。like “%aaa%” 不會使用索引而like “aaa%”可以使用索引。 - 不要在列上進行運算
例如:select * from users where YEAR(adddate)<2007姐军,將在每個行上進行運算铁材,這將導(dǎo)致索引失效而進行全表掃描,因此我們可以改成:select * from users where adddate<’2007-01-01′奕锌。
關(guān)于這一點可以圍觀:一個單引號引發(fā)的MYSQL性能損失著觉。
關(guān)于測試數(shù)據(jù),引用文章并沒有提 所以 我自己生成了一個10w的數(shù)據(jù)表
生成教程網(wǎng)址:mysql快速生成百萬條測試數(shù)據(jù)的方法