索引覆蓋是指如果查詢的列恰好是索引的一部分,那么查詢只需要在索引文件上進行,不需要回行到磁盤再找數(shù)據(jù)。這種查詢速度非???稱為”索引覆蓋”
十余年的沙雅網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整沙雅建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。創(chuàng)新互聯(lián)公司從事“沙雅網(wǎng)站設(shè)計”,“沙雅網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。
? ? 1查詢頻繁????2區(qū)分度高????3長度小????4盡量能覆蓋常用查詢字段
索引長度直接影響索引文件的大小,影響增刪改的速度,并間接影響查詢速度(占用內(nèi)存多)。因此對于一些長短不同的字節(jié),我們會針對列中的值,從左往右截取部分,來建索引。但是:
1:截的越短, 重復(fù)度越高,區(qū)分度越小, 索引效果越不好
2:截的越長, 重復(fù)度越低,區(qū)分度越高, 索引效果越好,但帶來的影響也越大--增刪改變慢,并間影響查詢速度.
所以,我們要在 ?區(qū)分度 + 長度 ?兩者上,取得一個平衡( distinct?去重 )
? ? select count (distinct?left (word,6)) / count (*) from tablename;
對于一般的系統(tǒng)應(yīng)用區(qū)別度能達到 0.1 ,索引的性能就可以接受.
? ? alter table tablename add index word(word(4));
給字符串類型的字段建立索引效率不高,但是必須要經(jīng)常查這個字段怎么建索引?
比如說一個字段url,類型是字符串。那么可以建一個字段 crcurl 來存儲url字段crc32后的值,并給 crcurl 建立索引。
???crc32:循環(huán)冗余校驗。根據(jù)網(wǎng)上數(shù)據(jù)包或計算機文件等數(shù)據(jù)產(chǎn)生簡短固定位數(shù)校驗碼的一種散列函數(shù),主要用來檢測或校驗數(shù)據(jù)傳輸或者保存后可能出現(xiàn)的錯誤。生成的數(shù)字在傳輸或者存儲之前計算出來并且附加到數(shù)據(jù)后面,然后接收方進行檢驗確定數(shù)據(jù)是否發(fā)生變化。一般來說,循環(huán)冗余校驗的值都是32位的整數(shù)。
crc32 是整形,在MySQL中,給整形字段建立索引效率比較高,crc32雖然不能確保唯一性,但是無礙,相同的機率也是極小,關(guān)鍵是可以大大減少查詢的范圍,給crcurl這個字段建立索引,查詢的時候帶上crcurl字段就可以利用到索引。
? ? ? ? 不允許翻過100頁(百度搜索一般到70頁左右)?
首先我們直接大數(shù)據(jù)分頁limit 5000000,10? 發(fā)現(xiàn)耗時4.41秒
接下來我們轉(zhuǎn)換方式使用where條件查詢,只耗時0.02秒
? ? ? ? 2次的查詢結(jié)果不一致,這是因為數(shù)據(jù)被物理刪除過有空洞.,因此我們可以追加軟刪除功能
分析:優(yōu)化思路是 不查,少查,查索引,少取.
我們現(xiàn)在必須要查,則只查索引,不查數(shù)據(jù),得到id.
再用id去查具體條目. ?這種技巧就是延遲索引.
? ? 分析:limit是先查詢再越過,也就是說我們先查詢出所有數(shù)據(jù)再進行跳躍,上圖我們越過500W頁,還使用了inner?join? 內(nèi)存并沒有崩掉,這是因為我們子句tmp臨時表中只查詢了id(索引覆蓋,不需要回行去磁盤找數(shù)據(jù)了)然后拿到這10個id?分別查詢這10條數(shù)據(jù) 。
排序可能發(fā)生2種情況:
1:對于覆蓋索引,直接在索引上查詢時,就是有順序的, using index
2:先取出數(shù)據(jù),形成臨時表做filesort(文件排序,但文件可能在磁盤上,也可能在內(nèi)存中)
我們的爭取目標(biāo):取出來的數(shù)據(jù)本身就是有序的! 利用索引來排序,那么什么時候發(fā)生索引排序呢?即查詢索引和order by的字段是同一個字段
???goods表中 cat_id與shop_price組成聯(lián)合索引:
select goods_id,cat_id,shop_price from goods where cat_id=4 order by shop_price;????可以直接利用索引來排序,
using where按照shop_price索引取出的結(jié)果,本身就是有序的
? ? ?????select goods_id,cat_id,shop_price from goods order by click_count;
? ? ? ? ? using filesort用到了文件排序,即取出的結(jié)果再次排序
重復(fù)索引是指 在同1個列(如age), 或者順序相同的幾個列(age,school), 建立了多個索引,稱為重復(fù)索引,重復(fù)索引沒有任何幫助,只會增大索引文件,拖慢更新速度。
冗余索引是指2個索引所覆蓋的列有重疊, 稱為冗余索引。比如x,m,列,加索引 index x(x), ?index xm(x,m) x,xm索引, 兩者的x列重疊了, ?這種情況,稱為冗余索引. (mx, xm 不是重復(fù)的,因為列的順序不一樣)
索引是在存儲引擎中實現(xiàn)的,也就是說不同的存儲引擎,會使用不同的索引。MyISAM和InnoDB存儲引擎:只支持BTREE索引,也就是說默認使用BTREE,不能夠更換,MySQL5.7中InnoDB可以支持HASH索引;MEMORY/HEAP存儲引擎:支持HASH和BTREE索引。索引可劃分為單列索引(其中包括普通索引、唯一索引、主鍵索引)、組合索引、全文索引、空間索引,其中單列索引是一個索引只包含單個列,但一個表中可以有多個單列索引。
MySQL中基本索引類型,沒有什么限制,允許在定義索引的列中插入重復(fù)值和空值,純粹為了查詢數(shù)據(jù)更快一點。
索引列中的值必須是唯一的,但是允許為空值,
是一種特殊的唯一索引,不允許有空值。
在表中的多個字段組合上創(chuàng)建的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引才會被使用,使用組合索引時遵循最左前綴集合。
由id、name和age3個字段構(gòu)成的索引,索引行中就按id/name/age的順序存放,索引可以索引下面字段組合(id,name,age)、(id,name)或者(id)。如果要查詢的字段不構(gòu)成索引最左面的前綴,那么就不會是用索引,比如,age或者(name,age)組合就不會使用索引查詢
全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT類型字段上使用全文索引。全文索引就是在一堆文字中,通過其中的某個關(guān)鍵字等,就能找到該字段所屬的記錄行,比如有"你是個大牛,神人 ..." 通過大牛,可能就可以找到該條記錄。這里說的是可能,因為全文索引的使用涉及了很多細節(jié),我們只需要知道這個大概意思。
只有在MyISAM引擎上才能使用,空間索引是對空間數(shù)據(jù)類型的字段建立的索引,MySQL中的空間數(shù)據(jù)類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。
在創(chuàng)建空間索引時,使用SPATIAL關(guān)鍵字。
創(chuàng)建空間索引的列,必須將其聲明為NOT NULL。。
SPATIAL INDEX spatIdx(g)
全值匹配我最愛,最左前綴要遵守;
帶頭大哥不能死,中間兄弟不能斷;
索引列上少計算,范圍之后全失效;
Like百分寫最右,覆蓋索引不寫星;
不等空值還有or,索引失效要少用;
VAR引號不可丟,SQL高級也不難!
參考: u;/u
參考: u;/u
如果索引包含滿足查詢的所有數(shù)據(jù),就稱為覆蓋索引。覆蓋索引是一種非常強大的工具,能大大提高查詢性能。只需要讀取索引而不用讀取數(shù)據(jù)有以下一些優(yōu)點:
(1) 索引項通常比記錄要小,所以MySQL訪問更少的數(shù)據(jù);
(2) 索引都按值的大小順序存儲,相對于隨機訪問記錄,需要更少的I/O;
(3) 大多數(shù)據(jù)引擎能更好的緩存索引。比如MyISAM只緩存索引。
(4) 覆蓋索引對于InnoDB表尤其有用,因為InnoDB使用聚集索引組織數(shù)據(jù),如果二級索引中包含查詢所需的數(shù)據(jù),就不再需要在聚集索引中查找了。
覆蓋索引不能是任何索引,只有B-TREE索引存儲相應(yīng)的值。而且不同的存儲引擎實現(xiàn)覆蓋索引的方式都不同,并不是所有存儲引擎都支持覆蓋索引(Memory和Falcon就不支持)。
對于索引覆蓋查詢(index-covered query),使用EXPLAIN時,可以在Extra一列中看到“Using index”。
產(chǎn)品中有一張圖片表,數(shù)據(jù)量將近100萬條,有一條相關(guān)的查詢語句,由于執(zhí)行頻次較高,想針對此語句進行優(yōu)化。表結(jié)構(gòu)很簡單,主要字段:
user_id 用戶ID
picname 圖片名稱
smallimg 小圖名稱
一個用戶會有多條圖片記錄,現(xiàn)在有一個根據(jù)user_id建立的索引:uid,查詢語句也很簡單。取得某用戶的圖片集合
執(zhí)行查詢語句(為了查看真實執(zhí)行時間,強制不使用緩存)
執(zhí)行了10次,平均耗時在40ms左右。使用explain進行分析
使用了user_id的索引,并且是const常數(shù)查找,表示性能已經(jīng)很好了
因為這個語句太簡單,sql本身沒有什么優(yōu)化空間,就考慮了索引。修改索引結(jié)構(gòu),建立一個(user_id,picname,smallimg)的聯(lián)合索引:uid_pic。重新執(zhí)行10次,平均耗時降到了30ms左右。使用explain進行分析
看到使用的索引變成了剛剛建立的聯(lián)合索引,并且Extra部分顯示使用了'Using Index'
'Using Index'的意思是“覆蓋索引”,它是使上面sql性能提升的關(guān)鍵。一個包含查詢所需字段的索引稱為“覆蓋索引”,MySQL只需要通過索引就可以返回查詢所需要的數(shù)據(jù),而不必在查到索引之后進行回表操作,減少IO,提高了效率。
例如上面的sql,查詢條件是user_id,可以使用聯(lián)合索引,要查詢的字段是picname smallimg,這兩個字段也在聯(lián)合索引中,這就實現(xiàn)了“覆蓋索引”,可以根據(jù)這個聯(lián)合索引一次性完成查詢工作,所以提升了性能
InnoDB存儲引擎由于實現(xiàn)了行級鎖定,雖然在鎖定機制的實現(xiàn)方面帶來的性能損耗可能比表級鎖定要更高一些,但是在整體并發(fā)處理能力方面是要遠遠優(yōu)于MyISAM的表級鎖定的。當(dāng)系統(tǒng)并發(fā)量較高的時候,InnoDB的整體性能和MyISAM相比就會有比較明顯的優(yōu)勢了。但是當(dāng)我們使用不當(dāng)?shù)臅r候,可能會讓InnoDB的整體性能表現(xiàn)不僅不比MyISAM高,甚至可能會更差。
建議:
(1)盡可能讓所有的數(shù)據(jù)檢索都通過索引來完成,從而避免InnoDB因為無法通過索引鍵加鎖而升級為表級鎖定
(2)合理設(shè)計索引,讓InnoDB在索引鍵上面加鎖的時候盡可能準(zhǔn)確,盡可能地縮小鎖定范圍,避免造成不必要的鎖定而影響其他Query的執(zhí)行
(3)盡可能減少基于范圍的數(shù)據(jù)檢索過濾條件,避免因為間隙鎖帶來的負面影響而鎖定了不該鎖定的記錄
(4)盡量控制事務(wù)的大小,減少鎖定的資源量和鎖定時間長度
(5)在業(yè)務(wù)環(huán)境允許的情況下,盡量使用較低級別的事務(wù)隔離,以減少MySQL因為實現(xiàn)事務(wù)隔離級別所帶來的附加成本。
上一篇給小伙伴們講了關(guān)于SQL查詢性能優(yōu)化的相關(guān)技巧,一個好的查詢SQL離不開合理的索引設(shè)計。這篇小二就來嘮一嘮怎么合理的設(shè)計一個索引來優(yōu)化我們的查詢速度,要是有不合理的地方...嗯..
當(dāng)然啦,開個玩笑,歡迎小伙伴們指正!
通常情況下,字段類型的選擇是需要根據(jù)業(yè)務(wù)來判斷的,通常需要遵循以下幾點。
下列各種類型表格內(nèi)容來自菜鳥教程,權(quán)當(dāng)備忘。
優(yōu)化建議:
注意: INT(2)設(shè)置的為顯示寬度,而不是整數(shù)的長度,需要配合 ZEROFILL 使用 。
例如 id 設(shè)置為 TINYINT(2) UNSIGNED ,表示無符號,可以存儲的最大數(shù)值為255,其中 TINYINT(2) 沒有配合 ZEROFILL 實際沒有任何意義,例如插入數(shù)字200,長度雖然超過了兩位,但是這個時候是可以插入成功的,查詢結(jié)果同樣為200;插入數(shù)字5時,同樣查詢結(jié)果為5。
而 TINYINT(2) 配合 ZEROFILL 后,當(dāng)插入數(shù)字5時,實際存儲的還是5,不過在查詢是MySQL會在前面補上一個0,即查詢出來的實際為 05 。
優(yōu)化建議:
優(yōu)化建議:
通常來說,考慮好表中每個字段應(yīng)該使用什么類型和長度,建完表需要做的事情不是馬上建立索引,而是先把相關(guān)主體業(yè)務(wù)開發(fā)完畢,然后把涉及該表的SQL都拿出來分析之后再建立索引。
盡量少建立單值索引( 唯一索引除外 ),應(yīng)當(dāng)設(shè)計一個或者兩三個聯(lián)合索引,讓每一個聯(lián)合索引都盡量去包含SQL語句中的 where、order by、group by 的字段,同時確保聯(lián)合索引的字段順序盡量滿足SQL查詢的最左前綴原則。
索引基數(shù)是指這個字段在表里總共有多少個不同的值,比如一張表總共100萬行記錄,其中有個性別字段,性別一共有三個值:男、女、保密,那么該字段的基數(shù)就是3。
如果對這種小基數(shù)字段建立索引的話,因為索引樹中只有男、女、保密三個值,根本沒法進行快速的二分查找,同時還需要回表查詢,還不如全表掃描嘞。
一般建立索引,盡量使用那些基數(shù)比較大的字段,那么才能發(fā)揮出B+樹快速二分查找的優(yōu)勢來。
在 where 和 order by 出現(xiàn)索引設(shè)計沖突時,是優(yōu)先針對where去設(shè)計索引?還是優(yōu)先針對order by設(shè)計索引?
通常情況下都是優(yōu)先針對 where 來設(shè)計索引,因為通常情況下都是先 where 條件使用索引快速篩選出來符合條件的數(shù)據(jù),然后對進行篩選出來的數(shù)據(jù)進行排序和分組,而 where 條件快速篩選出來的的數(shù)據(jù)往往不會很多。
對生產(chǎn)實際運行過程中,或者測試環(huán)境大數(shù)據(jù)量測試過程中發(fā)現(xiàn)的慢查詢SQL進行特定的索引優(yōu)化、代碼優(yōu)化等策略。
終于輪到實戰(zhàn)了,小二最喜歡實戰(zhàn)了。
寫到這里不得不吐槽一下,這個金三銀四的跳槽季節(jié),年前提離職了,結(jié)果離職還沒辦完就封村整整兩個禮拜了,嗚嗚嗚...
上節(jié)小二就提到會有個很有意思的小案例,那么在疫情當(dāng)下,門都出不去的日子,感覺這個例子更有意思了,咱們來討論一下各種社交平臺怎么做的用戶信息搜索呢。
社交平臺有一個小伙伴們都喜歡的功能,搜索好友信息,比如小二熟練的點開省份...城市..性別..年齡..身高...
咳咳咳...小二怎么可能干這種事情,小二的心里只有代碼,嗯...沒錯,就是這樣。
這個就可以說是對于用戶信息的查詢篩選了,通常這種表都是非常大數(shù)據(jù)量的,在不考慮分庫分表的情況下,怎么通過索引配合SQL來優(yōu)化呢?
通常我們在編寫SQL是會寫出類似如下的SQL來執(zhí)行,有 where、order by、limit 等條件來查詢。
那么接下來小二一個一個慢慢增加字段來分析分析,怎么根據(jù)業(yè)務(wù)場景來設(shè)計索引。
針對這種情況,很簡單,設(shè)計一個聯(lián)合索引 (provice, city, sex) 就完事了。
那么這時候有小伙伴就會說了,很簡單啊,范圍字段放最后咱還是知道的,聯(lián)合索引改成 (provice, city, sex, age) 不就可以了。
嗯,是的,這么干沒毛病,但是小伙伴們有沒有想過有些人萬一既喜歡帥哥又喜歡美女,別想歪了哈...,挺多小姐姐就既喜歡帥哥又喜歡美女的。
那么這個時候小姐姐就不搜索性別了,那么這個時候聯(lián)合索引只能用到前兩個字段了,那么不符合咱們的專業(yè)標(biāo)準(zhǔn)啊,咋辦呢?這時候還是有辦法的,咱們只需要動動小腦袋改改SQL就行了,在沒有選擇性別時判斷一下,改成下面這樣就可以了。
咋辦嘞,同樣往聯(lián)合索引里面塞,例如 (provice, city, sex, hobby, xx, age) 。
針對這種多個范圍查詢的話,為了比較好的利用索引,在業(yè)務(wù)允許的情況下可以使用固定范圍,然后數(shù)據(jù)庫字段存儲范圍標(biāo)識就可以了,這樣就轉(zhuǎn)化為了等值匹配,就可以很好地利用索引了。
例如最后登錄時間字段不記錄最后登錄時間,而是記錄設(shè)置字段 is_login_within_seven_days 在7天內(nèi)有登錄則為1,否則為0,最后索引設(shè)計成 (provice, city, sex, hobby, xx, is_login_within_seven_days, age) 。
那么根據(jù)場景最后設(shè)計出來的這個索引可能已經(jīng)可以覆蓋大部分的查詢流量了,那么如果還有其他一部分熱度比較高的查詢怎么辦呢,辦法也很簡單啊,再加一兩個索引即可。
例如通常會查詢這個城市比較受歡迎(評分:score)的小姐姐,這時候添加一個聯(lián)合索引 (provice, city, sex, score) 那么就可以了。
可以看出,索引時必須結(jié)合場景來設(shè)計的,思路就是盡量用不超過3個復(fù)雜的聯(lián)合索引來抗住大部分的80%以上的常用查詢流量,然后再用一兩個二級索引來抗下一些非常用查詢流量。
以上就是小二要給大家分享的索引設(shè)計,如果能動動你發(fā)財?shù)男∈纸o小二點個免費的贊就更好啦~
下篇小二就來講講MySQL事務(wù)和鎖機制。
索引就是為特定的mysql字段進行一些特定的算法排序,比如二叉樹的算法和哈希算法,哈希算法是通過建立特征值,然后根據(jù)特征值來快速查找。
1.普通索引:(index)最基本的索引,沒有任何限制? 目的:加快數(shù)據(jù)的查詢速度
2.唯一索引:(unique)? 與"普通索引"類似,不同的就是:索引列的值必須唯一,但允許有空值。
3.主鍵索引(primary key) 它 是一種特殊的唯一索引,不允許有空值。
4.復(fù)合索引:index(a,b,c)? 為了更多的提高mysql效率可建立組合索引,遵循”最左前綴“原則。
5.全文索引:fulltext? 僅可用于 MyISAM 表,針對較大的數(shù)據(jù),生成全文索引很耗時耗空間。
第一類是myisam存儲引擎使用的叫做b-tree結(jié)構(gòu),
第二類是innodb存儲引擎使用的叫做聚簇結(jié)構(gòu)(也是一種 b-tree)。 如下圖:
注意:
1.myisam不需要回行處理?
2.innodb不需要回行處理,直接可以獲取數(shù)據(jù),因為innodb的儲存引擎是包含了數(shù)據(jù)和索引文件的,其主鍵索引包含了數(shù)據(jù),(唯一索引及普通索是沒有直接包含數(shù)據(jù)的)
1、索引列不能參與計算
有索引列參與計算的查詢條件對索引不友好(甚至無法使用索引),如from_unixtime(create_time) = '2014-05-29'。
原因很簡單,如何在節(jié)點中查找到對應(yīng)key?如果線性掃描,則每次都需要重新計算,成本太高;如果二分查找,則需要針對from_unixtime方法確定大小關(guān)系。
因此,索引列不能參與計算。上述from_unixtime(create_time) = '2014-05-29'語句應(yīng)該寫成create_time = unix_timestamp('2014-05-29')。
2、最左前綴匹配
如有索引(a, b, c, d),查詢條件a = 1 and b = 2 and c 3 and d = 4,則會在每個節(jié)點依次命中a、b、c,無法命中d。也就是最左前綴匹配原則。
3、冗余和重復(fù)索引
冗余索引是指在相同的列上按照相同的順序創(chuàng)建的相同類型的索引,應(yīng)當(dāng)盡量避免這種索引,發(fā)現(xiàn)后立即刪除。比如有一個索引(A,B),再創(chuàng)建索引(A)就是冗余索引。冗余索引經(jīng)常發(fā)生在為表添加新索引時,比如有人新建了索引(A,B),但這個索引不是擴展已有的索引(A)
4、避免多個范圍條件
? ? select user.* from user where login_time '2017-04-01' and age between 18 and 30;
比如想查詢某個時間段內(nèi)登錄過的用戶:它有兩個范圍條件,login_time列和age列,MySQL可以使用login_time列的索引或者age列的索引,但無法同時使用它們 .
5、覆蓋索引 (能擴展就不新建)
如果一個索引包含或者說覆蓋所有需要查詢的字段的值,那么就沒有必要再回表查詢,這就稱為覆蓋索引。覆蓋索引是非常有用的工具,可以極大的提高性能,因為查詢只需要掃描索引會帶來許多好處:
1.索引條目遠小于數(shù)據(jù)行大小,如果只讀取索引,極大減少數(shù)據(jù)訪問量2.索引是有按照列值順序存儲的,對于I/O密集型的范圍查詢要比隨機從磁盤讀取每一行數(shù)據(jù)的IO要少的多
6、選擇區(qū)分度高的列作索引
如,用性別作索引,那么索引僅能將1000w行數(shù)據(jù)劃分為兩部分(如500w男,500w女),索引幾乎無效。
區(qū)分度的公式是count(distinct ) / count(*),表示字段不重復(fù)的比例,比例越大區(qū)分度越好。唯一鍵的區(qū)分度是1,而一些狀態(tài)、性別字段可能在大數(shù)據(jù)面前的區(qū)分度趨近于0。
7、刪除長期未使用的索引
場景一(覆蓋索引 5)
索引應(yīng)該建在選擇性高的字段上(鍵值唯一的記錄數(shù)/總記錄條數(shù)),選擇性越高索引的效果越好、價值越大,唯一索引的選擇性最高;
組合索引中字段的順序,選擇性越高的字段排在最前面;
where條件中包含兩個選擇性高的字段時,可以考慮分別創(chuàng)建索引,引擎會同時使用兩個索引(在OR條件下,應(yīng)該說必須分開建索引);
不要重復(fù)創(chuàng)建彼此有包含關(guān)系的索引,如index1(a,b,c) 、index2(a,b)、index3(a);
組合索引的字段不要過多,如果超過4個字段,一般需要考慮拆分成多個單列索引或更為簡單的組合索引;
不要濫用索引。因為過多的索引不僅僅會增加物理存儲的開銷,對于插入、刪除、更新操作也會增加處理上的開銷,而且會增加優(yōu)化器在選擇索引時的計算代價。
因此太多的索引與不充分、不正確的索引對性能都是毫無益處的。一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應(yīng)該經(jīng)過仔細分析,要有建立的依據(jù)。
mysql的索引類型及使用索引時的注意事項有:
一、普通索引。這是最基本的索引,它沒有任何限制。它有以下幾種創(chuàng)建方式:
1、創(chuàng)建索引
代碼如下:
CREATE INDEX indexName ON mytable(username(length));
如果是CHAR,VARCHAR類型,length可以小于字段實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。
2、修改表結(jié)構(gòu)
代碼如下:
ALTER mytable ADD INDEX [indexName] ON (username(length)) -- 創(chuàng)建表的時候直接指定
CREATE TABLE mytable(?? ID INT NOT NULL,??? username VARCHAR(16) NOT NULL,?? INDEX [indexName] (username(length))?? );?
-- 刪除索引的語法:
DROP INDEX [indexName] ON mytable;
二、唯一索引。它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創(chuàng)建方式:
代碼如下:
CREATE UNIQUE INDEX indexName ON mytable(username(length))
-- 修改表結(jié)構(gòu)
ALTER mytable ADD UNIQUE [indexName] ON (username(length))
-- 創(chuàng)建表的時候直接指定
CREATE TABLE mytable(?? ID INT NOT NULL,??? username VARCHAR(16) NOT NULL,?? UNIQUE [indexName] (username(length))?? );
三、主鍵索引。它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創(chuàng)建主鍵索引:
代碼如下:
CREATE TABLE mytable(?? ID INT NOT NULL,??? username VARCHAR(16) NOT NULL,?? PRIMARY KEY(ID)?? );
當(dāng)然也可以用 ALTER 命令。記?。阂粋€表只能有一個主鍵。
四、組合索引。為了形象地對比單列索引和組合索引,為表添加多個字段:
代碼如下:
CREATE TABLE mytable(?? ID INT NOT NULL,??? username VARCHAR(16) NOT NULL,?? city VARCHAR(50) NOT NULL,?? age INT NOT NULL? );
為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:
代碼如下:
ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);[code]
建表時,usernname長度為 16,這里用 10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。
如果分別在 usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低于我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。
建立這樣的組合索引,其實是相當(dāng)于分別建立了下面三組組合索引:usernname,city,age?? usernname,city?? usernname? 為什么沒有 city,age這樣的組合索引呢?這是因為MySQL組合索引“最左前綴”的結(jié)果。簡單的理解就是只從最左面的開始組合。并不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:
[code]
SELECT * FROM mytable WHREE username="admin" AND city="鄭州"? SELECT * FROM mytable WHREE username="admin"
索引用于快速找到特定一些值的記錄。如果沒有索引,MySQL就必須從第一行記錄開始讀取整個表來檢索記錄。表越大,資源消耗越大。如果在字段上有索引的話,MySQL就能很快決定該從數(shù)據(jù)文件的哪個位置開始搜索記錄,而無須查找所有的數(shù)據(jù)。如果表中有1000條記錄的話,那么這至少比順序地讀取數(shù)據(jù)快100倍。注意,如果需要存取幾乎全部1000條記錄的話,那么順序讀取就更快了,因為這樣會使磁盤搜索最少。
大部分MySQL索引(PRIMARY KEY, UNIQUE,INDEX 和 FULLTEXT)都是以B樹方式存儲。只有空間類型的字段使用R樹存儲,MEMORY (HEAP)表支持哈希索引。
字符串默認都是自動壓縮前綴和后綴中的空格。
通常,如下所述幾種情況下可以使用索引。哈希索引(用于 MEMORY 表)的獨特之處在后面會討論到。
想要盡快找到匹配 WHERE 子句的記錄。
根據(jù)條件排除記錄。如果有多個索引可共選擇的話,MySQL通常選擇能找到最少記錄的那個索引。
做表連接查詢時從其他表中檢索記錄。
想要在指定的索引字段 key_col 上找到它的 MIN() 或 MAX() 值。優(yōu)化程序會在檢查索引的
key_col 字段前就先檢查其他索引部分是否使用了 WHERE key_part_# = constant 子句。這樣的話,
MySQL會為 MIN() 或 MAX() 表達式分別單獨做一次索引查找,并且將它替換成常數(shù)。當(dāng)所有的表達式都被替換成常數(shù)后,查詢就立刻返回。如下:
SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;
對表作排序或分組,當(dāng)在一個可用的最左前綴索引上做分組或排序時(如 ORDER
BY key_part1, key_part2)。如果所有的索引部分都按照 DESC 排序,索引就按倒序排序。
有些時候,查詢可以優(yōu)化使得無需計算數(shù)據(jù)就能直接取得結(jié)果。當(dāng)查詢使用表中的一個數(shù)字型字段,且這個字段是索引的最左部分,則可能從索引樹中能很快就取得結(jié)果:
SELECTkey_part3FROMtbl_nameWHEREkey_part1=1
假設(shè)有如下 SELECT 語句:
如果在 col1 和 col2 上有一個多字段索引的話,就能直接取得對應(yīng)的記錄了。
希望能解決您的問題。