首先說說索引的 優(yōu)點 :最大的好處無疑就是提高查詢效率。有的索引還能保證數(shù)據(jù)的唯一性,比如唯一索引。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名與空間、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、豐都網(wǎng)站維護、網(wǎng)站推廣。
而它的 壞處 也很明顯:索引也是文件,我們在創(chuàng)建索引時,也會創(chuàng)建額外的文件,所以會占用一些硬盤空間。其次,索引也需要維護,我們在增加刪除數(shù)據(jù)的時候,索引也需要去變化維護。當一個表的索引多了以后,資源消耗是很大的,所以必須結(jié)合實際業(yè)務(wù)再去確定給哪些列加索引。
再說說索引的基本結(jié)構(gòu)。一說到這里肯定會脫口而出:B+樹!了解B+樹前先要了解二叉查找樹和二叉平衡樹。 二叉查找樹 :左節(jié)點比父節(jié)點小,右節(jié)點比父節(jié)點大,所以二叉查找樹的中序遍歷就是樹的各個節(jié)點從小到大的排序。 二叉平衡樹 :左右子樹高度差不能大于1。B+樹就是結(jié)合了它們的特點,當然,不一定是二叉樹。
為什么要有二叉查找樹的特點?? 因為查找效率快,二分查找在這種結(jié)構(gòu)下,查找效率是很快的。 那為什么要有平衡樹的特點呢? 試想,如果不維護一顆樹的平衡性,當插入一些數(shù)據(jù)后,樹的形態(tài)有可能變得很極端,比如左子樹一個數(shù)據(jù)沒有,而全在右子樹上,這種情況下,二分查找和遍歷有什么區(qū)別呢?而就是因為這些特點需要去維護,所以就有了上面提到的缺點,當索引很多后,反而增加了系統(tǒng)的負擔。
接著說B+樹。 它的結(jié)構(gòu)如下 :
可以發(fā)現(xiàn),葉子節(jié)點其實是一個 雙向循環(huán)鏈表 ,這種結(jié)構(gòu)的好處就是,在范圍查詢的時候,我只用找到一個數(shù)據(jù),就可以直接返回剩余的數(shù)據(jù)了。比如找小于30的,只用找到30,其余的直接通過葉子節(jié)點間的指針就可以找到。再說說其他特點: 數(shù)據(jù)只存在于葉子節(jié)點 。當葉子節(jié)點滿了,如果再添加數(shù)據(jù),就會拆分葉子節(jié)點,父節(jié)點就多了個子節(jié)點。如果父節(jié)點的位置也滿了,就會擴充高度,就是拆分父節(jié)點,如25 50 75拆分成:25為左子樹,75為右子樹,50變成新的頭節(jié)點,此時B+樹的高度變成了3。它們的擴充的規(guī)律如下表,Leaf Page是葉子節(jié)點,index Page是非葉子節(jié)點。
再說說B樹 ,B樹相比較B+樹,它所有節(jié)點都存放數(shù)據(jù),所以在查找數(shù)據(jù)時,B樹有可能沒到達葉子節(jié)點就結(jié)束了。再者,B樹的葉子節(jié)點間不存在指針。
最后說說Hash索引 ,相較于B+樹,Hash索引最大的優(yōu)點就是查找數(shù)據(jù)快。但是Hash索引最大的問題就是不支持范圍查詢。試想,如果查詢小于30的數(shù)據(jù),hash函數(shù)是根據(jù)數(shù)據(jù)的值找到其對應(yīng)的位置,誰又知道小于30的有哪幾個數(shù)據(jù)。而B+樹正好相反,范圍查詢是它的強項。
附錄: Hash到底是啥?? 哈希中文名散列,哈希只是它的音譯。 為啥都說Hash快?? 首先有一塊哈希表(散列表),它的數(shù)據(jù)結(jié)構(gòu)是個數(shù)組,一個任意長度的數(shù)據(jù)通過hash函數(shù)都可以變成一個固定長度的數(shù)據(jù),叫hash值。然后通過hash值確定在數(shù)組中的位置,相同數(shù)據(jù)的hash值是相同的,所以我們存儲一個數(shù)據(jù)以后,只需O(1)的時間復(fù)雜度就可以找到數(shù)據(jù)。 那hash函數(shù)又是啥?? 算術(shù)運算或位運算,很多應(yīng)用里都有hash函數(shù),但實際運算過程大不一樣。這是Java里String的hashCode方法:
publicint hashCode() {
}
還有一個問題,hash函數(shù)計算出來的hash值有可能存在碰撞,即兩個不同的數(shù)據(jù)可能存在相同的hash值,在MySQL或其他的應(yīng)用中,如Java的HashMap等,如果存在碰撞就會以當前數(shù)組位置為頭節(jié)點,轉(zhuǎn)變成一個鏈表。
說到這里也清楚了為啥Java中引用類型要同時重寫hashCode和equals了。兩個對象,實例就算一模一樣,它們的hash值也不相等, 為啥不相等?? 默認的Object的hashCode方法會根據(jù)對象來計算hash值的,實例相同,但它們還是兩個不同的對象啊,所以我們重寫hashCode時,最簡單的方法就是調(diào)用Object的hashCode方法,然后傳入該引用類型的屬性,讓hashCode方法只根據(jù)這幾個屬性來計算,那么實例相同的話,它們的hash值也會相等。等hashCode比較完后,如果相等再比較實例內(nèi)容,也就是equals,確保不是hash碰撞。
索引的分類
如果我們指定了一個主鍵,那么這個主鍵就是主鍵索引。如果我們沒有指定,Mysql就會自動找一個非空的唯一索引當主鍵。如果沒有這種字段,Mysql就會創(chuàng)建一個大小為6字節(jié)的自增主鍵。如果有多個非空的唯一索引,那么就讓第一個定義為唯一索引的字段當主鍵,注意,是第一個定義,而不是建表時出現(xiàn)在前面的。
對于輔助索引來說,它們的B+樹結(jié)構(gòu)稍微有點特殊,它們的葉子節(jié)點存儲的是主鍵,而不是整個數(shù)據(jù)。所以在大部分情況下,使用輔助索引查找數(shù)據(jù),需要二次查找。但并不是所有情況都需要二次查找。比如查找的數(shù)據(jù)正好就是當前索引字段的值,那么直接返回就行。這里提一句,B+樹的key就是對應(yīng)索引字段的內(nèi)容。
而輔助索引又有一些分類:唯一索引:不能出現(xiàn)重復(fù)的值,也算一種約束。普通索引:可以重復(fù)、可以為空,一般就是查詢時用到。前綴索引:只適用于字符串類型數(shù)據(jù),對字符串前幾個字符創(chuàng)建索引。全文索引:作用是檢測大文本數(shù)據(jù)中某個關(guān)鍵字,這也是搜索引擎的一種技術(shù)。
注意,聚集索引、非聚集索引和前面幾個索引的分類并不是一個層面上的。上面的幾個分類是從索引的作用來分析的。聚集、非聚集索引是從索引文件上區(qū)分的。主鍵索引就屬于聚集索引,即索引和數(shù)據(jù)存放在一起,葉子節(jié)點存放的就是數(shù)據(jù)。數(shù)據(jù)表的.idb文件就是存放該表的索引和數(shù)據(jù)。
輔助索引屬于非聚集索引,說到這也就明白了。索引和數(shù)據(jù)不存放在一起的就是非聚集索引。在MYISAM引擎中,數(shù)據(jù)表的.MYI文件包含了表的索引, 該表的 葉子節(jié)點存儲索引和索引對應(yīng)數(shù)據(jù)的指針,指向.MYD文件的數(shù)據(jù)。
索引的幾點使用經(jīng)驗
經(jīng)常被查詢的字段;經(jīng)常作為條件查詢的字段;經(jīng)常用于外鍵連接或普通的連表查詢時進行相等比較字段;不為null的字段;如果是多條件查詢,最好創(chuàng)建聯(lián)合索引,因為聯(lián)合索引只有一個索引文件。
經(jīng)常被更新的字段、不經(jīng)常被查詢的字段、存在相同功能的字段
字符串創(chuàng)建索引方式:
1、直接創(chuàng)建完整索引,比較占用空間。
2、創(chuàng)建前綴索引,節(jié)省空間,但會增加查詢掃描次數(shù),并且不能使用覆蓋索引。
3、倒序存儲,在創(chuàng)建前綴索引,用于繞過字符串本身前綴的卻分度不夠的問題。
4、創(chuàng)建hash字段索引,查詢性能穩(wěn)定,有額外的存儲和計算消耗。
倒序存儲和hash字段索引都不支持范圍查詢。倒序存儲的字段上創(chuàng)建的所有是按照倒序字符串的方式排序的。hash字段的方式也只能支持等值查詢。
mysql alter table SUser add index index1(email); :包含了每個記錄的整個字符串
或
mysql alter table SUser add index index2(email(6)); :-對于每個記錄只取前6個字節(jié)
全字段索引操作流程
使用的是 index1(即 email 整個字符串的索引結(jié)構(gòu)),執(zhí)行順序是這樣的:
1、從 index1 索引樹找到滿足索引值是’ zhangssxyz@xxx.com ’的這條記錄,取得 ID2 的值;
2、到主鍵上查到主鍵值是 ID2 的行,判斷 email 的值是正確的,將這行記錄加入結(jié)果集;
3、取 index1 索引樹上剛剛查到的位置的下一條記錄,發(fā)現(xiàn)已經(jīng)不滿足 email=' zhangssxyz@xxx.com ’的條件了,循環(huán)結(jié)束。
前綴字段索引操作流程
如果使用的是 index2(即 email(6) 索引結(jié)構(gòu)),執(zhí)行順序是這樣的:
1、從 index2 索引樹找到滿足索引值是’zhangs’的記錄,找到的第一個是 ID1;
2、到主鍵上查到主鍵值是 ID1 的行,判斷出 email 的值不是’ zhangssxyz@xxx.com ’,這行記錄丟棄;
3、取 index2 上剛剛查到的位置的下一條記錄,發(fā)現(xiàn)仍然是’zhangs’,取出 ID2,再到 ID 索引上取整行然后判斷,這次值對了,將這行記錄加入結(jié)果集;
4、重復(fù)上一步,直到在 idxe2 上取到的值不是’zhangs’時,循環(huán)結(jié)束。
倒序查詢和hash字段的區(qū)別
它們的區(qū)別,主要體現(xiàn)在以下三個方面:
1、從占用的額外空間來看,倒序存儲方式在主鍵索引上,不會消耗額外的存儲空間,而 hash 字段方法需要增加一個字段。當然,倒序存儲方式使用 4 個字節(jié)的前綴長度應(yīng)該是不夠的,如果再長一點,這個消耗跟額外這個 hash 字段也差不多抵消了。
2、在 CPU 消耗方面,倒序方式每次寫和讀的時候,都需要額外調(diào)用一次 reverse 函數(shù),而 hash 字段的方式需要額外調(diào)用一次 crc32() 函數(shù)。如果只從這兩個函數(shù)的計算復(fù)雜度來看的話,reverse 函數(shù)額外消耗的 CPU 資源會更小些。
3、從查詢效率上看,使用 hash 字段方式的查詢性能相對更穩(wěn)定一些。因為 crc32 算出來的值雖然有沖突的概率,但是概率非常小,可以認為每次查詢的平均掃描行數(shù)接近 1。而倒序存儲方式畢竟還是用的前綴索引的方式,也就是說還是會增加掃描行數(shù)。
1.添加PRIMARY KEY(主鍵索引) mysqlALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 2.添加UNIQUE(唯一索引) mysqlALTER TABLE `table_name` ADD UNIQUE ( `column` ) 3.添加INDEX(普通索引) mysqlALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 4.添加FULLTEXT(全文索引) mysqlALTER TABLE `table_name` ADD FULLTEXT ( `column`) 5.添加多列索引 mysqlALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
索引用于快速找到特定一些值的記錄。如果沒有索引,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ù)。當所有的表達式都被替換成常數(shù)后,查詢就立刻返回。如下:
SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;
對表作排序或分組,當在一個可用的最左前綴索引上做分組或排序時(如 ORDER
BY key_part1, key_part2)。如果所有的索引部分都按照 DESC 排序,索引就按倒序排序。
有些時候,查詢可以優(yōu)化使得無需計算數(shù)據(jù)就能直接取得結(jié)果。當查詢使用表中的一個數(shù)字型字段,且這個字段是索引的最左部分,則可能從索引樹中能很快就取得結(jié)果:
SELECTkey_part3FROMtbl_nameWHEREkey_part1=1
假設(shè)有如下 SELECT 語句:
如果在 col1 和 col2 上有一個多字段索引的話,就能直接取得對應(yīng)的記錄了。
網(wǎng)頁題目:mysql怎么添加哈希索,mysql的哈希索引
URL地址:http://jinyejixie.com/article8/dssesip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站維護、、企業(yè)建站、微信公眾號、服務(wù)器托管
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)