第五章 索引與算法 閱讀總結(jié)

????????索引是應(yīng)用程序設(shè)計和開發(fā)的一個重要方面。 若索引太多, 應(yīng)用程序的性能可能會受到影響。 而索引太少, 對查詢性能又會產(chǎn)生影響。 要找到一個合適的平衡點, 這對應(yīng)用程序的性能至關(guān)重要。

? ??????一些開發(fā)人員總是在事后才想起添加索引——我一直認為, 這源于一種錯誤的開發(fā)模式。 如果知道數(shù)據(jù)的使用, 從一開始就應(yīng)該在需要處添加索引。 開發(fā)人員往往對于數(shù)據(jù)庫的使用停留在應(yīng)用的層面, 比如編寫 SQL 語句、 存儲過程之類, 他們甚至可能不知道索引的存在, 或者認為事后讓相關(guān)OBA加上即可。 OBA往往不夠了解業(yè)務(wù)的數(shù)據(jù)流,而添加索引需要通過監(jiān)控大量的 SQL 語句進而從中找到問題, 這個步驟所需的時間肯定是遠大于初始添加索引所需要的時間, 并且可能會遺漏一部分的索引。 當然索引也并不是越多越好。

5.1?lnnoDB 存儲引擎索引概述

?InnoDB 存儲引擎支持以下幾種常見的索引:

1.B+樹索引

2.全文索引

3.哈希索引

????????前面已經(jīng)提到過, lnnoDB 存儲引擎支持的哈希索引是自適應(yīng)的, lnnoDB 存儲引擎會根據(jù)表的使用情況自動為表生成哈希索引, 不能人為干預(yù)是否在一張表中生成哈希索引。

? ?????B+樹索引就是傳統(tǒng)意義上的索引,這是目前關(guān)系型數(shù)據(jù)庫系統(tǒng)中查找最為常用和最為有效的索引。B+樹索引的構(gòu)造類似于二叉樹,根據(jù)鍵值(KeyValue)快速找到數(shù)據(jù)。?

????????注意B+樹中的B不是代表二叉(binary),而是代表平衡(balance),因為B+樹是從最早的平衡二叉樹演化而來,但是B+樹不是一個二叉樹。? ???

????????另一個常常被DBA 忽視的問題是: B+ 樹索引并不能找到一個給定鍵值的具體行。? ?B+ 樹索引能找到的只是被查找數(shù)據(jù)行所在的頁。然后數(shù)據(jù)庫通過把頁讀入到內(nèi)存,再在內(nèi)存中進行查找,最后得到要查找的數(shù)據(jù)。

5.2 數(shù)據(jù)結(jié)構(gòu)與算法

????????????B+ 樹索引是最為常見,也是在數(shù)據(jù)庫中使用最為頻繁的一種索引。在介紹該索引之前先介紹與之密切相關(guān)的一些算法與數(shù)據(jù)結(jié)構(gòu),這有助于讀者更好的理解B+ 樹索引的工作方式。

5.2.1 二分查找法

? ??????二分查找法(binary search) 也稱為折半查找法,用來查找一組有序的記錄數(shù)組中的某一記錄,其基本思想是:將記錄按有序化(遞增或遞減)排列,在查找過程中采用跳躍式方式查找,即先以有序數(shù)列的中點位置為比較對象,如果要找的元素值小于該中點元素,則將待查序列縮小為左半部分,否則為右半部分。通過一次比較,將查找區(qū)間縮小一半。

5.3 B+樹

????????前面討論的都是B+樹的數(shù)據(jù)結(jié)構(gòu)及其一般操作,B+樹索引的本質(zhì)就是B+樹在數(shù)據(jù)庫中的實現(xiàn)。但是B+索引在數(shù)據(jù)庫中有一個特點是高扇出性,因此在數(shù)據(jù)庫中,B+樹的高度一般都在2-4 層,這也就是說查找某一鍵值的行記錄時最多只需要2-4次IO, 這倒不錯。因為當前一般的機械磁盤每秒至少可以做100 次IO, 2 ~4 次的IO 意味著查詢時間只需0.02~0.04 秒。

????????數(shù)據(jù)庫中的B+ 樹索引可以分為聚集索引(clustered inex) 和輔助索引(secondaryindex) 9, 但是不管是聚集還是輔助的索引,其內(nèi)部都是B+ 樹的,即高度平衡的,葉子節(jié)點存放著所有的數(shù)據(jù)。聚集索引與輔助索引不同的是,葉子節(jié)點存放的是否是一整行的信息。

5.4.1 聚集索引

? ??????之前已經(jīng)介紹過了, InnoDB 存儲引擎表是索引組織表,即表中數(shù)據(jù)按照主鍵順序存放。而聚集索引(clustered index) 就是按照每張表的主鍵構(gòu)造一棵B+ 樹,同時葉子節(jié)點中存放的即為整張表的行記錄數(shù)據(jù),也將聚集索引的葉子節(jié)點稱為數(shù)據(jù)頁。聚集索引的這個特性決定了索引組織表中數(shù)據(jù)也是索引的一部分。同B+ 樹數(shù)據(jù)結(jié)構(gòu)一樣,每個數(shù)據(jù)頁都通過一個雙向鏈表來進行鏈接。

????????由于實際的數(shù)據(jù)頁只能按照一棵B+ 樹進行排序,因此每張表只能擁有一個聚集索引。在多數(shù)情況下,查詢優(yōu)化器傾向于采用聚集索引。因為聚集索引能夠在B+ 樹索引的葉子節(jié)點上直接找到數(shù)據(jù)。此外,由于定義了數(shù)據(jù)的邏輯順序,聚集索引能夠特別快地訪問針對范圍值的查詢。查詢優(yōu)化器能夠快速發(fā)現(xiàn)某一段范圍的數(shù)據(jù)頁需要掃描。

? ??????聚集索引的存儲并不是物理上連續(xù)的,而是邏輯上連續(xù)的。這其中有兩點: 一是前面說過的頁通過雙向鏈表鏈接,頁按照主鍵的順序排序;另一點是每個頁中的記錄也是通過雙向鏈表進行維護的,物理存儲上可以同樣不按照主鍵存儲。

????????聚集索引的另一個好處是,它對于主鍵的排序查找和范圍查找速度非常快。葉子節(jié)點的數(shù)據(jù)就是用戶所要查詢的數(shù)據(jù)。如用戶需要查詢一張注冊用戶的表,查詢最后注冊的10 位用戶,由于B+樹索引是雙向鏈表的,用戶可以快速找到最后一個數(shù)據(jù)頁,并取出10條記錄

5.4.2 輔助索引

? ??????對于輔助索引(Secondary Index, 也稱非聚集索引), 葉子節(jié)點并不包含行記錄的全部數(shù)據(jù)。 葉子節(jié)點除了包含鍵值以外, 每個葉子節(jié)點中的索引行中還包含了 個書簽(bookmark)。 該書簽用來告訴InnoDB存儲引擎哪里可以找到與索引相對應(yīng)的行數(shù)據(jù)。 由于InnoDB存儲引擎表是索引組織表, 因此lnnoDB存儲引擎的輔助索引的書簽就是相應(yīng)行數(shù)據(jù)的聚集索引鍵。 圖5-15顯示了InnoDB存儲引擎中輔助索引與聚集索引的關(guān)系。

? ??????輔助索引的存在并不影響數(shù)據(jù)在聚集索引中的組織, 因此每張表上可以有多個輔助索引。 當通過輔助索引來尋找數(shù)據(jù)時,lnnoDB存儲引擎會遍歷輔助索引并通過葉級別的指針獲得指向主鍵索引的主鍵,然后再通過主鍵索引來找到一個完整的行記錄。

? ??????當然,在一些情況下,使用堆表的確會比索引組織表更快,但是我覺得大部分原因是由于存在 OLAP(On-Line Analy tical Processing, 在線分析處理)的應(yīng)用。其次就是前面提到的,表中數(shù)據(jù)是否需要更新,并且更新是否影響到物理地址的變更。此外另一個不能忽視的是對于排序和范圍查找,索引組織表通過B+樹的中間節(jié)點就可以找到要查找的所有頁,然后進行讀取,而堆表的特性決定了這對其是不能實現(xiàn)的。最后,非聚集索引的離散讀,的確存在上述的情況,但是一般的數(shù)據(jù)庫都通過實現(xiàn)預(yù)讀(read ahead) 技術(shù)來避免多次的離散讀操作。因此,具體是建堆表還是索引組織表,這取決于應(yīng)用, 不存在哪個更優(yōu)的問題。這和InnoDB存儲引擎好還是MyISAM存儲引擎好這個問題的答案是一樣的,It all depends。

5.4.3 B+ 樹索引的分裂

? ??????在5.3節(jié)中介紹 B+樹的分裂是最為簡單的一種情況, 這和數(shù)據(jù)庫中 B+ 樹索引的情況可能略有不同。 此外5.3節(jié)頁沒有涉及并發(fā), 而這才是 B+ 樹索引實現(xiàn)最為困難的部分。

????????B+ 樹索引頁的分裂并不總是從頁的中間記錄開始, 這樣可能會導(dǎo)致頁空間的浪費。例如下面的記錄:1、 2 、 3、 4 、 5 、 6、 7 、 8、 9

? ??????插入是根據(jù)自增順序進行的, 若這時插人10這條記錄后需要進行頁的分裂操作, 那么根據(jù)5.3.1節(jié)介紹的分裂方法, 會將記錄5作為分裂點記錄(split record), 分裂后得到下面兩個頁:Pl: 1、 2 、 3、 4

P2: 5、6、7、8、9、 10

? ??????然而由千插入是順序的,Pl這個頁中將不會再有記錄被插人, 從而導(dǎo)致空間的浪費。 而P2又會再次進行分裂。

? ??????InnoDB存儲引擎的Page Header中有以下幾個部分用來保存插入的順序信息:

PAGE_LAST_INSERT

PAGE_DIRECTION

PAGE_N_DIRECTION

? ??????通過這些信息, InnoDB 存儲引擎可以決定是向左還是向右進行分裂, 同時決定將分裂點記錄為哪一個。 若插入是隨機的, 則取頁的中間記錄作為分裂點的記錄, 這和之前介紹的相同。 若往同一方向進行插入的記錄數(shù)量為5, 并且目前已經(jīng)定位(cursor)到的記錄 (InnoDB 存儲引擎插入時, 首先需要進行定位, 定位到的記錄為待插入記錄的前一條記錄)之后還有3條記錄, 則分裂點的記錄為定位到的記錄后的第三條記錄, 否則分裂點記錄就是待插人的記錄。

5.4.4 B+樹索引的管理

1. 索引管理

????????索引的創(chuàng)建和刪除可以通過兩種方法, 一種是ALTER TABLE, 另一種是CREATE/DROP INDEX。

????????用戶可以設(shè)置對整個列的數(shù)據(jù)進行索引, 也可以只索引一個列的開頭部分數(shù)據(jù).若用戶想要查看表中索引的信息,可以使用命令SHOW INDEX。

? ??????通過命令SHOWINDEX FROM可以觀察到表t上有4個索引,分別為主鍵索引、c列上的輔助索引、b列的前100字節(jié)構(gòu)成的輔助索引,以及(a、c)的聯(lián)合輔助索引。接著具體闡述命令SHOWINDEX展現(xiàn)結(jié)果中每列的含義。

Table: 索引所在的表名。

Non_unique: 非唯一的索引,可以看到primary key是 o, 因為必須是唯一的。

?Key_name: 索引的名字,用戶可以通過這個 名字來執(zhí)行 DROP INDEX。

Seq_in_index: 索引中該 列的位置,如果看聯(lián)合索引idx_a_c就比較直觀了。 0 Column_name: 索引列的名稱。

Collation : 列以什么方式存儲在索引中。可以是A或NULL。B+樹索引總是A,即排序的。如果使用了Heap 存儲引擎,并且建立了Hash索引,這里就會顯示NULL了。因為Hash根據(jù)Hash桶存放索引數(shù)據(jù),而不是對數(shù)據(jù)進行排序。

Cardinality: 非常關(guān)鍵的值,表示索引中唯一值的數(shù)目的估計值。Cardinality表的行數(shù)應(yīng)盡可能接近1, 如果非常小,那么用戶需要考慮是否 可以刪除此索引。

?Sub_part : 是否是列的部分被索引。如果看idx_b這個索引,這里顯示100, 表示只對b列的前100字符進行索引。如果索引整個列,則該 字段為NULL。

?Packed: 關(guān)鍵字如何被壓縮。如果沒有被壓縮,則為NULL。

Null: 是否索引的列含有NULL值??梢钥吹絠dx_b這里為Yes, 因為定義的列b允許NULL值。

Index_ type : 索引的類型。InnoDB存儲引擎只支持B+樹索引,所以這里顯示的都是 BTREE。

Comment: 注釋。

? ??????Cardinality值非常關(guān)鍵,優(yōu)化器會根據(jù)這個值來判斷是否使用這個索引。但是這個值并不是實時更新 的,即并非每次索引的更新都會 更新該值,因為這樣代價太大了。因此這個值是不太準確的只是一個大概的值。上面顯示的結(jié)果主鍵的Cardinality為2, 但是很顯然我們的表中有4條記錄,這個值應(yīng)該 是4。如果需要更新索引Cardinality 的信息,可以使用ANALYZE TABLE命令。

2. Fast Index Creation

? ?????lnnoDB存儲引擎從InnoDB 1.0.x版本開始支持一種稱為FastIndex Creation (快速索引創(chuàng)建)的索引創(chuàng)建方式——簡稱FIC。

????????對于輔助索引的創(chuàng)建,InnoDB存儲引擎會對創(chuàng)建索引的表加上一個S鎖。在創(chuàng)建的過程中,不需要重建表, 因此速度較之前提高很多, 并且數(shù)據(jù)庫的可用性也得到了提高。刪除輔助索引操作就更簡單了,InnoDB存儲引擎只需更新內(nèi)部視圖, 并將輔助索引的空間標記為可用,同時刪除MySQL數(shù)據(jù)庫內(nèi)部視圖上對該表的索引定義即可。

????????這里需要特別注意的是, 臨時表的創(chuàng)建路徑是通過參數(shù)tmpdir 進行設(shè)置的。用戶必須保證tmpdir有足夠的空間可以存放臨時表,否則會導(dǎo)致創(chuàng)建索引失敗。

????????由于FIC在索引的創(chuàng)建的過程中對表加上了S鎖, 因此在創(chuàng)建的過程中只能對該表進行讀操作, 若有大址的事務(wù)需要對目標表進行寫操作, 那么數(shù)據(jù)庫的服務(wù)同樣不可用。此外,F(xiàn)IC方式只限定于輔助索引, 對于主鍵的創(chuàng)建和刪除同樣需要重建一張表。

3. Online Schema Change

? ??????Online Schema Change (在線架構(gòu)改變, 簡稱OSC)最早是由Facebook實現(xiàn)的一種在線執(zhí)行DDL的方式, 并廣泛地應(yīng)用于Facebook的MySQL數(shù)據(jù)庫。所謂“在線” 是指在事務(wù)的創(chuàng)建過程中,可以有讀寫事務(wù)對表進行操作, 這提高了原有MySQL數(shù)據(jù)庫在DDL操作時的并發(fā)性。

????????Facebook采用PHP腳本來現(xiàn)實OSC, 而并不是通過修改InnoDB存儲引擎源碼的方式。osc 最初由Facebook 的員工VamsiPonnekanti開發(fā)。此外, osc 借鑒了開源社區(qū)之前的工具The openarkkit toolkit oak-online-alter-table。實現(xiàn)osc 步驟如下:

init, 即初始化階段,會對創(chuàng)建的表做一些驗證工作, 如檢查表是否有主鍵, 是否存在觸發(fā)器或者外鍵等。

?createCopyTable, 創(chuàng)建和原始表結(jié)構(gòu)一樣的新表。

?alterCopyTable: 對創(chuàng)建的新表進行ALTER TABLE 操作, 如添加索引或列等。

?createDeltasTable, 創(chuàng)建deltas表, 該表的作用是為下一步創(chuàng)建的觸發(fā)器所使用。之后對原表的所有DML操作會被記錄到createDeltasTable 中。

create Triggers, 對原表創(chuàng)建INSERT、UPDATE、DELETE 操作的觸發(fā)器。觸發(fā)操作產(chǎn)生的記錄被寫入到deltas表。

startSnpshotXact, 開始osc 操作的事務(wù)。

selectTablelntoOutfile, 將原表中的數(shù)據(jù)寫人到新表。為了減少對原表的鎖定時間, 這里通過分片(chunked)將數(shù)據(jù)輸出到多個外部文件, 然后將外部文件的數(shù)據(jù)導(dǎo)人到copy表中。分片的大小可以指定, 默認值是500 000。

?dropNCindexs, 在導(dǎo)人到新表前, 刪除新表中所有的輔助索引。

loadCopyTable, 將導(dǎo)出的分片文件導(dǎo)入到新表。

replayChanges, 將osc 過程中原表DML操作的記錄應(yīng)用到新表中, 這些記錄被保存在deltas表中。

recreateNCindexes, 重新創(chuàng)建輔助索引。

replayChanges, 再次進行DML日志的回放操作, 這些日志是在上述創(chuàng)建輔助索引中過程中新產(chǎn)生的日志。

swapTables, 將原表和新表交換名字, 整個操作需要鎖定2張表, 不允許新的數(shù)據(jù)產(chǎn)生。由于改名是一個很快的操作, 因此阻塞的時間非常短。

????????上述只是簡單介紹了osc 的實現(xiàn)過程, 實際腳本非常復(fù)雜, 僅osc 的PHP核心代碼就有22 00 多行, 用到的MySQLInnoDB 的知識點非常多, 建議OBA 和數(shù)據(jù)庫開發(fā)人員嘗試進行閱讀, 這有助于更好地理解InnoDB存儲引擎的使用。

????????由于osc 只是一個PHP腳本, 因此其有一定的局限性。例如其要求進行修改的表一定要有主鍵, 且表本身不能存在外鍵和觸發(fā)器。此外, 在進行osc 過程中, 允許SETsql_b in_l og=O, 因此所做的操作不會同步slave服務(wù)器,可能 導(dǎo)致主從不一致的情況。

4. Online DDL

? ??????雖然FIC可以讓InnoDB存儲引擎避免創(chuàng)建臨時表, 從而提高索引創(chuàng)建的效率。但正如前面小節(jié)所說的, 索引創(chuàng)建時會阻塞表上的DML操作。osc 雖然解決了上述的部分問題, 但是還是有很大的局限性。MySQL5.6版本開始支持Online DDL (在線數(shù)據(jù)定義)操作,其允許輔助索引創(chuàng)建的同時,還允許其他諸如INSERT、UPDATE、DELETE這類DML操作,這極大地提高了MySQL數(shù)據(jù)庫在生產(chǎn)環(huán)境中的可用性。

此外,不僅是輔助索引,以下這幾類DDL操作都可以 通過“在線” 的方式進行操作:

輔助索引的創(chuàng)建與刪除

改變自增長值

添加或刪除外鍵約束

列的重命名

過新的 ALTER TABLE語法,用戶可以選擇索引的創(chuàng)建方式:

? ??????ALGORITHM指定了創(chuàng)建或刪除索引的算法,COPY表示按照MySQL5.l版本之前的工作模式, 即創(chuàng)建臨時表的方式。INPLACE表示索引創(chuàng)建或刪除操作不需要創(chuàng)建臨時表。DEFAULT表示根據(jù)參數(shù)old_alter_ table來判斷是通過INPLACE還是COPY的算法,該參數(shù)的默認值為OFF, 表示采用INPLACE的方式

LOCK部分為索引創(chuàng)建或刪除時對表添加鎖的情況, 可有的選擇為:

(I) NONE

執(zhí)行索引創(chuàng)建或者刪除操作時,對目標表不添加任何的鎖, 即事務(wù)仍然可以進行讀寫操作,不會收到阻塞。因此這種模式可以獲得最大的并發(fā)度。

(2) SHARE

這和之前的FIC類似, 執(zhí)行索引創(chuàng)建或刪除操作時, 對目標表加上一個并發(fā)地讀事務(wù),依然可以執(zhí)行,但是遇到寫事務(wù),就會發(fā)生等待操作。如果存儲引擎不支持SHARE模式,會返回一個錯誤信息。

(3) EXCLUSIVE

在EXCLUSIVE模式下, 執(zhí)行索引創(chuàng)建或刪除操作時,對目標表加上一個X鎖。讀寫事務(wù)都 不能進行,因此會阻塞所有的線程,這和COPY方式運行得到的狀態(tài)類似,但是不需要像COPY方式那樣創(chuàng)建一張臨時表。

(4) DEFAULT

DEFAULT模式首先會判斷當前操作是否可以使用NONE模式,若不能,則判斷是否可以使用SHARE模式,最 后判斷是否可以使用EXCLUSIVE模式。也就是說DEFAULT會通過判斷事務(wù)的最大并發(fā)性來判斷執(zhí)行DDL的模式。

????????InnoDB存儲引擎實現(xiàn)OnlineDDL的原理是在執(zhí)行創(chuàng)建或者刪除操作的同時,將 INSER T、 UPDATE、DELE TE這類DML操作日志寫入到一個緩存中。待完成索引創(chuàng)建后再將重做應(yīng)用到表上,以此 達到數(shù)據(jù)的 一致性。這個緩存的大小由參數(shù)innodb_ online _alter_ log_ max_ size控制,默認的大小 為128MB 。

5.5 Cardinality值

5.5.1 什么是Cardinality

? ??????并不是在所有的查詢條件中出現(xiàn)的列都需要添加索引。對于什么時候添加B+樹索引, 一般的經(jīng)驗是,在訪問表中很少一部分時使用B+樹索引才有意義。對于性別字段,地區(qū)字段、類型字段,它們可取值的范圍很小,稱為低選擇性。

? ??????按性別進行查詢時,可取值的范圍一般只有'M'、'F'。因此上述SQL語句得到的結(jié)果可能是該表50%的數(shù)據(jù)(假設(shè)男女比例1 : 1), 這時添加B+樹索引是完全沒有必要的。相反,如果某個字段的取值范圍很廣,幾乎沒有重復(fù),即屬于高選擇性,則此時使用B+樹索引是最適合的。例如,對于姓名字段,基本上在一個應(yīng)用中不允許重名的出現(xiàn)。

? ??????怎樣查看索引是否是高選擇性的呢?可以通過SHOW INDEX結(jié)果中的列Cardinality來觀察。Cardinality值非常關(guān)鍵,表示索引中不重復(fù)記錄數(shù)扭的預(yù)估值。同時需要注意的是Cardinality是一個預(yù)估值,而不是一個準確值,基本上用戶也不可能得到一個準確的值。在實際應(yīng)用中,CardinalityIn_ row s_ in_ table應(yīng)盡可能地接近1。如果非常小,那么用戶需要考慮是否還有必要創(chuàng)建這個索引。故在訪問高選擇性屬性的字段并從表中取出很少一部分數(shù)據(jù)時,對這個字段添加B+樹索引是非常有必要的。

5.5.2 lnnoDB存儲引擎的Cardinality統(tǒng)計

????????因為MySQL數(shù)據(jù)庫中有各種不同的存儲引擎, 而每種存儲引擎對于B+樹索引的實現(xiàn)又各不相同, 所以對Cardinality的統(tǒng)計是放在存儲 引擎層進行的。數(shù)據(jù)庫對于 Cardinality的統(tǒng)計都是通過采樣(Sample)的方法來完成的。

InnoDB存儲引擎內(nèi)部對更新Cardinality信息的策略為:

表中 1/16 的數(shù)據(jù)已發(fā)生過變化。

stat_modified_counter>2 000 000 000。

????????第一種策略為自從上次統(tǒng)計Cardinality信息后, 表中 1/16 的數(shù)據(jù)已經(jīng)發(fā)生過變化,這時需要更新Cardinality信息。 第二種情況考慮的是, 如果對表中某一行數(shù)據(jù)頻繁地進行更新操作, 這時表中的數(shù)據(jù)實際并沒有增加, 實際發(fā)生變化的還是這一行數(shù)據(jù), 則第一種更新策略就無法適用這這種情況。 故在InnoDB存儲引擎內(nèi)部有一個計數(shù)器stat_ modified_ counter, 用來表示發(fā)生變化的次數(shù), 當stat_modified_ counter大于2 000 000 000 時, 則同樣需要更新Cardinality信息。

????????接著考慮InnoDB存儲引擎內(nèi)部是怎樣來進行Cardinality信息的統(tǒng)計和更新操作的 呢?同樣是通過采樣的方法。 默認InnoDB存儲引擎對8個葉子節(jié)點(Leaf Page)進行采用。 采樣的過程如下:

取得B+樹索引中葉子節(jié)點的數(shù)量, 記為A。

隨機取得B+樹索引中的8個葉子節(jié)點。 統(tǒng)計每個頁不同記錄的個數(shù), 即為P1,P2, …,P8。

根據(jù)采樣信息給出Cardinality的預(yù)估值:Cardinality= (Pl+ P2+…+P8) *A/8。

? ??????通過上述的說明可以發(fā)現(xiàn),在InnoDB存儲引擎中,Cardinality值是通過對8個葉子節(jié)點預(yù)估而得的,不是一個實際精確的值。再者,每次對Cardinality值的統(tǒng)計,都是通過隨機取8個葉子節(jié)點得到的,這同時又暗示了另一個Cardinality現(xiàn)象,即每次得到的Cardinality值可能是不同的。

5.6 B+樹索引的使用

5.6.1 不同應(yīng)用中B+樹索引的使用

? ???根據(jù)第1章的介紹,用戶已經(jīng)知道數(shù)據(jù)庫中存在兩種類型的應(yīng)用,OLTP和OLAP 應(yīng)用。在OLTP應(yīng)用中,查詢操作只從數(shù)據(jù)庫中取得一小部分數(shù)據(jù),一般可能都在10條? 記錄以下,甚至在很多時候只取1條記錄,如根據(jù)主鍵值來取得用戶信息,根據(jù)訂單號取得訂單的詳細信息,這都是典型OLTP應(yīng)用的查詢語句。在這種情況下,B+樹索引建立后,對該索引的使用應(yīng)該只是通過該索引取得表中少部分的數(shù)據(jù)。這時建立索引才有意義。否則優(yōu)化器可能選擇不執(zhí)行索引。????????對于OLAP應(yīng)用,情況可能就稍顯復(fù)雜了。不過概括來說,在OLAP應(yīng)用中,都需要訪問表中大批的數(shù)據(jù),根據(jù)這些數(shù)據(jù)來產(chǎn)生查詢的結(jié)果,這些查詢多是面向分析的查詢,目的是為決策者提供支持。如這個月每個用戶的消費情況,銷售額同比、環(huán)比增長 的情況。因此在OLAP中索引的添加根據(jù)的應(yīng)該是宏觀的信息,而不是微觀,因為最終要得到的結(jié)果是提供給決策者的。例如不需要在OLAP中對姓名字段進行索引,因為很 少需要對單個用戶進行查詢。但是對于OLAP中的復(fù)雜查詢,要涉及多張表之間的聯(lián)接操作,因此索引的添加依然是有意義的。但是,如果聯(lián)接操作使用的是HashJoin, 那么 索引可能又變得不是非常重要了,所以這需要OBA或開發(fā)人員認真并仔細地研究自己 的應(yīng)用。不過在OLAP應(yīng)用中,通常需要根據(jù)時間維度來進行數(shù)據(jù)的篩選。

5.6.2 聯(lián)合索引

? ??????聯(lián)合索引是指對表上的多個列進行索引。前面討論的情況都是只對表上的一個列進行索引。聯(lián)合索引的創(chuàng)建方法與單個索引創(chuàng)建的方法一樣,不同之處僅在于有多個索引列。

? ??????從本質(zhì)上來說,聯(lián)合索引也是一棵I I LI I _I I B+樹,不同的是聯(lián)合索引的鍵值的數(shù)量不是1,而是大于等于2。接著來討論兩個整型列組成的聯(lián)合索引,假定兩個鍵值的名稱分別為a、b,如圖5-22所示。

? ??????聯(lián)合索引的第二個好處是已經(jīng)對第二個鍵值進行了排序處理。例如,在很多情況下 應(yīng)用程序都需要查詢某個用戶的購物情況,并按照時間進行排序,最后取出最近三次的購買記錄,這時使用聯(lián)合索引可以避免多一次的排序操作,因為索引本身在葉子節(jié)點已 經(jīng)排序了。

5.6.3 覆蓋索引

? ??????InnoDB存儲引擎支持覆蓋索引(covering index, 或稱索引覆蓋),即從輔助索引中就可以得到查詢的記錄,而不需要查詢聚集索引中的記錄。使用覆蓋索引的一個好處是輔助索引不包含整行 記錄的所有信息,故其大小要遠小于聚集索引,因此可以減少大量的IO操作。

? ??????對于 InnoDB存儲引擎的輔助索引而言,由于其包含了主鍵信息,因此其葉子節(jié)點存放的數(shù)據(jù)為(primary key I , primary key2, …, keyl, key2, …)。

5.6.4 優(yōu)化器選擇不使用索引的情況

? ??????在某些情況下, 當執(zhí)行EXPLAIN命令進行SQL語句的分析時, 會發(fā)現(xiàn)優(yōu)化器并沒 有選擇索引去查找數(shù)據(jù), 而是通過掃描聚集索引, 也就是直接進行全表的掃描來得到數(shù)據(jù)。 這種情況多發(fā)生于范圍查找、JOIN鏈接操作等情況下。

5.6.5 索引提示

????????MySQL數(shù)據(jù)庫支持索引提示(INDEXHINT), 顯式地告訴優(yōu)化器使用哪個索引。個人總結(jié)以下兩種情況可能需要用到INDEXHINT:

????????MySQL數(shù)據(jù)庫的優(yōu)化器錯誤地選擇了某個索引, 導(dǎo)致SQL語句運行的很慢。這種情況在最新的MySQL數(shù)據(jù)庫版本中非常非常的少見。優(yōu)化器在絕大部分情況下工作得都非常有效和正確。這時有經(jīng)驗的OBA或開發(fā)人員可以強制優(yōu)化器使用某個索引, 以此來提高SQL運行的速度。

????????某SQL語句可以選擇的索引非常多, 這時優(yōu)化器選擇執(zhí)行計劃時間的開銷可能會大于SQL語句本身。例如, 優(yōu)化器分析Range查詢本身就是比較耗時的操作。這時DBA或開發(fā)人員分析最優(yōu)的索引選擇, 通過Index Hint來強制使優(yōu)化器不進行各個執(zhí)行路徑的成本分析, 直接選擇指定的索引來完成查詢。

5.6.6 Multi-Range Read優(yōu)化

? ??????MySQL5.6版本開始支持Multi-Range Read (MRR)優(yōu)化。 Multi-Range Read優(yōu)化的目的就是為了減少磁盤的隨機訪問, 并且將隨機訪問轉(zhuǎn)化為較為順序的數(shù)據(jù)訪問, 這對于IO-bound類型的 SQL查詢語句可帶來性能極大的提升。 Multi-Range Read優(yōu)化可適 用于range, ref, eq_ref類型的查詢。

?MRR優(yōu)化有以下幾個好處:

1 MRR使數(shù)據(jù)訪問變得較為順序。 在查詢輔助索引時, 首先根據(jù)得到的查詢結(jié)果 ,按照主鍵進行排序, 并按照主鍵排序的順序進行書簽查找。

2 減少緩沖池中頁被替換的次數(shù)。

3 批量處理對鍵值的查詢操作 。

對于lnnoDB 和MylSAM存儲引擎的范圍查詢和JOIN查詢操作, MRR的工作方式如下:

1 將查詢得到的 輔助索引鍵值存放于一個緩存中, 這時緩存中的數(shù)據(jù)是根據(jù)輔助索引鍵值排序的。

2 將緩存中的鍵值根據(jù)RowID進行排序。

3 根據(jù)RowID的排序順序來訪問實際的數(shù)據(jù)文件。

5.6.7 Index Condition Pushdown CICP)優(yōu)化

????????和Multi-Range Read 樣,Index Condition Pushdown同樣是 MySQLS.6開始支持的一種根據(jù)索引進行查詢的優(yōu)化方式。之前的數(shù)據(jù)庫當進行索引查詢時,首先根據(jù)索引來查找記錄,然后再根據(jù)WHERE條件來過濾記錄。 在支持Index Condition Pushdown后,MySQL數(shù)據(jù)庫會在取出索引的同時,判斷是否可以進行WHERE條件的過濾 ,也就是將WHERE 的部分過濾操作放在了存儲引擎層。 在某些查詢下, 可以大大減少上層SQL層對記錄的索取(fetch), 從而提高數(shù)據(jù)庫的整體性能。

? ??????Index Condition Pushdown優(yōu)化支持range、ref、eq_ref、ref_or_null類型的查詢, 當 前支持MylSAM和InnoDB存儲引擎 。 當優(yōu)化器選擇Index Condition Pushdown優(yōu)化時, 可在執(zhí)行計劃的列Extra看到Using index condition提示。

5.7 哈希算法

????????哈希算法是一種常見算法,時間復(fù)雜度為0 (1), 且不只存在于索引中,每個數(shù)據(jù)庫應(yīng)用中都存在該數(shù)據(jù)庫結(jié)構(gòu)。設(shè)想一個問題,當前服務(wù)器的內(nèi)存為 128GB 時,用戶怎么從內(nèi)存中得到某一個被緩存的頁呢?雖然內(nèi)存中查詢速度很快,但是也不可能每次都要遍歷所有內(nèi)存來進行查找,這時對于字典操作只需0 (1)的哈希算法就有了很好的用武之地。

5.7.1 ?哈希表

????????哈希表(HashTable)也稱散列表, 由直接尋址表改進而來。 我們先來看直接尋址 表。 當關(guān)鍵字的全域U比較小時, 直接尋址是一種簡單而有效的技術(shù)。 假設(shè)某應(yīng)用要用到 個動態(tài)集合, 其中每個元素都有一個取自全域U={0, 1, …,m-1}關(guān)鍵字。 同時假設(shè)沒有兩個元素具有相同的關(guān)鍵字。



????????直接尋址技術(shù)存在一個很明顯的問題, 如果域U很大, 在一臺典型計算機的可用容量的限制下, 要在機器中存儲大小為U的一張表T就有點不實際, 甚至是不可能的。 如果實際要存儲的關(guān)鍵字集合K相對于U來說很小, 那么分配給T的大部分空間都要浪費掉。

????????因此, 哈希表出現(xiàn)了。 在哈希方式下, 該元素處于h(k) 中, 即利用哈希函數(shù)h,根據(jù)關(guān)鍵字k計算出槽的位置。 函數(shù)h將關(guān)鍵字域U映射到哈希表T [O .. m-1]的槽位上, 如圖5-39所示。

? ??????哈希表技術(shù)很好地解決了直接尋址遇到的問題, 但是這樣做有一個小問題, 如圖5-39所示的兩個關(guān)鍵字可能映射到同一個槽上。 般將這種情況稱之為發(fā)生了碰撞(collision)。 在數(shù)據(jù)庫中一般采用最簡單的碰撞解決技術(shù), 這種技術(shù)被稱為鏈接法(chaining)。

? ? ? ?在鏈接法中, 把散列到同一槽中的所有元素都放在一個鏈表中, 如圖5-40所示。 槽j中有一個指針, 它指向由所有散列到j(luò)的元素構(gòu)成的鏈表的頭;如果不存在這樣的元素,則j中為NULL。

????????最后要考慮的是哈希函數(shù)。 哈希函數(shù)h必須可以很好地進行散列。 最好的情況是能避免碰撞的發(fā)生。 即使不能避免, 也應(yīng)該使碰撞在最小程度下產(chǎn)生。 一般來說, 都將關(guān)鍵字轉(zhuǎn)換成自然數(shù), 然后通過除法散列、 乘法散列或全域散列來實現(xiàn)。 數(shù)據(jù)庫中一般采用除法散列的方法。

????????在哈希函數(shù)的除法散列法中, 通過取k除以 m 的余數(shù), 將關(guān)鍵字k映射到 m個槽的某一個去, 即哈希函數(shù)為:h(k) = k mod m

5. 7 .2 lnnoDB 存儲引擎中的哈希算法

? ??????InnoDB 存儲引擎使用哈希算法來對字典進行查找, 其沖突機制采用鏈表方式, 哈希函數(shù)采用除法散列方式。 對于緩沖池頁的哈希表來說, 在緩沖池中的 Pag頁都有一個chain指針,它指向相同哈希函數(shù)值的頁。 而對于除法散列,m的取值為略大于2倍的緩沖池頁數(shù)量的質(zhì)數(shù)。 例如: 當前參數(shù)innodb _buffer _pool_ size的大小為lOM, 則共有640個16KB的頁。 對于緩沖池頁內(nèi)存的哈希表來說,需要分配640X2=1280個槽,但是由千1280不是質(zhì)數(shù),需要取比1280略大的一個質(zhì)數(shù),應(yīng)該是 1399, 所以在啟動時會分配 1399個槽的哈希表,用來哈希查詢所在緩沖池中的頁。

? ??????那么InnoDB存儲引擎的緩沖池對于其中的頁是怎么進行查找的呢?上面只是給出了一般的算法, 怎么將要查找的頁轉(zhuǎn)換成自然數(shù)呢?

? ??????其實也很簡單,InnoDB存儲引擎的表空間都有一個space_id, 用戶所要查詢的應(yīng)該是某個表空間的某個連續(xù)16KB的頁, 即偏移量offset。lnnoDB存儲引擎將space_id左移20位, 然后加上這個space_id和offset, 即關(guān)鍵字K=space_ id<<20+space id+offset,然后通過除法散列到各個槽中去。

5.7.3 自適應(yīng)哈希索引

? ??????自適應(yīng)哈希索引采用之前討論的哈希表的方式實現(xiàn)。不同的是, 這僅是數(shù)據(jù)庫自身創(chuàng)建并使用的, DBA本身并不能對其進行干預(yù)。自適應(yīng)哈希索引經(jīng)哈希函數(shù)映射到一個哈希表中, 因此對于字典類型的查找非??焖?,如SELECT * FROM TABLE WHERE index_col='xxx'。但是對于范圍查找就無能為力了。。通過命令SHOW ENGINE INNODB STATUS可以看到當前自適應(yīng)哈希索引的使用狀況。

? ??????現(xiàn)在可以看到自適應(yīng)哈希索引的使用信息了,包括自適應(yīng)哈希索引的大小,使用情況、每秒使用自適應(yīng)哈希索引搜索的情況。需要注意的是,哈希索引只能用來搜索等值的查詢。

? ??????而對于其他查找類型,如范圍查找,是不能使用哈希索引的。因此,這里出現(xiàn)了non-hash searches/s的情況。通過hashsearches:non-hash searches可以大概了解使用哈希索引后的效率。

????????由于自適應(yīng)哈希索引是由InnoDB存儲引擎自己控制的,因此這里的這些信息只供參考。不過可以通過參數(shù)innodb_adaptive_ hash_ index來禁用或啟動此特性,默認為開啟。

5.8 全文檢索

5.8.1 概述

? ??????通過前面章節(jié)的介紹,已經(jīng)知道B+樹索引的特點,可以通過索引字段的前綴(prefix)進行查找。例如,對于下面的查詢B+樹索引是支持的:SELECT* FROM blog WHERE content like'xxx%'

? ??????上述SQL語句可以查詢博客內(nèi)容以XXX開頭的文章,并且只要content添加了B+ 樹索引,就能利用索引進行快速查詢。然而實際這種查詢不符合用戶的要求,因為在更多的情況下,用戶需要查詢的是博客內(nèi)容包含單詞xxx的文章,即:SELECT* FROM blog WHERE content like'%xxx%'

????????根據(jù)B+樹索引的特性,上述SQL語句即便添加了B+樹索引也是需要進行索引的掃描來得到結(jié)果。類似這樣的需求在互聯(lián)網(wǎng)應(yīng)用中還有很多。例如,搜索引擎需要根據(jù)用戶輸入的關(guān)鍵字進行全文查找,電子商務(wù)網(wǎng)站需要根據(jù)用戶的查詢條件,在可能需要在商品的詳細介紹中進行查找,這些都不是B+樹索引所能很好地完成的工作。

????????全文檢索(Full-TextSearch)是將存儲于數(shù)據(jù)庫中的整本書或整篇文章中的任意內(nèi)容信息查找出來的技術(shù)。它可以根據(jù)需要獲得全文中有關(guān)章、節(jié)、段、句、詞等信息,也可以進行各種統(tǒng)計和分析。

? ??????在之前的MySQL數(shù)據(jù)庫中,InnoDB存儲引擎并不支持全文檢索技術(shù)。大多數(shù)的用戶轉(zhuǎn)向MyISAM存儲引擎,這可能需要進行表的拆分,并將需要進行全文檢索的數(shù)據(jù)存儲為 MyISAM 表。這樣的確能夠解決邏輯業(yè)務(wù)的需求,但是卻喪失了 InnoDB 存儲引擎的事務(wù)性,而這在生產(chǎn)環(huán)境應(yīng)用中同樣是非常關(guān)鍵的。

????????從 InnoDB 1.2.x 版本開始,InnoDB 存儲引擎開始支持全文檢索,其支持 MyISAM存儲引擎的全部功能,并且還支持其他的一些特性,這些將在后面的小節(jié)中進行介紹。

5.8.2 倒排索引

? ??????全文檢索通常使用倒排索引 (inverted index) 來實現(xiàn)。倒排索引同 B+ 樹索引一樣,也是一種索引結(jié)構(gòu)。它在輔助表(auxiliarytable)中存儲了單詞與單詞自身在一個或多個文檔中所在位置之間的映射。這通常利用關(guān)聯(lián)數(shù)組實現(xiàn),其擁有兩種表現(xiàn)形式:

inverted file index, 其表現(xiàn)形式為{單詞,單詞所在文檔的 ID}

?full inverted index, 其表現(xiàn)形式為{單詞,(單詞所在文檔的ID, 在具體文檔中的位置)}

5.8.3 InnoDB全文檢索

? ??????InnoDB存儲引擎從1.2.x版本開始支持全文檢索的技術(shù),其采用full inverted index 的方式。在InnoDB存儲引擎中,將(Documentld, Position)視為一個"ilist"。因此在全文檢索的表中,有兩個列,一個是word字段,另一個是 ilist字段,并且在word字段上有設(shè)有索引。此外,由于InnoDB存儲引擎在 ilist字段中存放了 Position信息,故可以進行Proximity Search, 而MyISAM存儲引擎不支持該特性。

????????正如之前所說的那樣, 倒排索引需要將word存放到一張表中,這個 表稱為Auxiliary Table (輔助表) 。在InnoDB存儲引擎中, 為了提高全文檢索的并行性能,共有6張Auxiliary Table, 目前每張表根據(jù)word的Latin編碼進行分區(qū)。

? ??????Auxiliary Table是持久的表,存放于磁盤上。然而在InnoDB存儲引擎的全文索引中,還有另外一個重要的概念FTSIndex Cache (全文檢索索引緩存),其用來提高全文檢索的性能。

? ??????FTS Index Cache是一個紅黑樹結(jié)構(gòu),其根據(jù)(word, ilist)進行排序。這意味著插入的數(shù)據(jù)已經(jīng)更新了對應(yīng)的表,但是對全文索引的更新可能在分詞操作后還在?FTS Index Cache中,AuxiliaryTable可能還沒有更新。InnoDB存儲引擎會批量對Auxilible 進行更新,而不是每次插入后更新一次AuxiliaryTable。當對全文檢索進行查詢時, Auxiliary Table首先會將在FTSIndex Cache中對應(yīng)的word字段合并到AuxiliaryTable 中,然后再進行查詢。這種merge操作非常類似之前介紹的InsertBuffer的功能,不同的是InsertBuffer是一個持久的對象,并且其是B+樹的結(jié)構(gòu)。然而FTSIndex Cache的作用又和InsertBuffer是類似的,它提高了InnoDB存儲引擎的性能,并且由于其根據(jù)紅黑樹排序后進行批量插人,其產(chǎn)生的AuxiliaryTable相對較小。

????????InnoDB存儲引擎允許用戶查看指定倒排索引的Auxiliary Table中分詞的信息, 可以通過設(shè)置參數(shù)innodb_ft_aux_table來觀察倒排索引的Auxiliary Table。

? ??????當數(shù)據(jù)庫關(guān)閉時,在FTSIndex Cache中的數(shù)據(jù)庫會同步到磁盤上的Auxiliary Table中。然而 ,如果當數(shù)據(jù)庫 發(fā)生右機時, 些FTSIndex Cache中的數(shù)據(jù)庫 可能未被同步到磁盤上。那么下次重啟數(shù)據(jù)庫 時,當用戶對表進行全文檢索(查詢或者插入操作)時,

????????lnnoDB存儲引擎會自動讀取未完成的文檔,然后進行分詞操作, 再將分詞的結(jié)果放入到FTS Index Cache中。

????????參數(shù)innodb_ft_ cache_ size 用來控制FTSIndex Cache的大小 ,默認值為32M。當該緩存滿時,會將其中的(word, ilist)分詞信息同步到磁盤的Auxiliary Table中。增大該參數(shù)可以提高全文檢索的性能,但是在者機時,未同步到磁盤中的索引信息可能需要更長的時間進行恢復(fù)。

? ??????FTS Document ID是另外一個重要的概念。在lnnoDB存儲引擎中,為了支持全文檢索,必須有一個列與word進行映射,在InnoDB中這個列被命名為FTS_DOC_ID,其類型必須是BIGINTUNSIGNED NOT NULL, 并且InnoDB存儲引擎自動會在該列上加入一個名為FTS_DOC_ID_INDEX的UniqueIndex。上述這些操作都由lnnoDB存儲引擎自已完成,用戶也可以在建表時自動添加FTS_DOC _ID, 以及相應(yīng)的UniqueIndex。由千列名為FTS_DOC_ID的列具有特殊意義,因此創(chuàng)建時必須注意相應(yīng)的類型,否則MySQL數(shù)據(jù)庫會拋出錯誤。

? ??????文檔中分詞的插入操作是在事務(wù)提交時完成,然而對于刪除操作,其在事務(wù)提交時,不刪除磁盤Auxiliary Table中的記錄,而只是刪除 FTS Cache Index中的記錄。 對 于Auxiliary Table中被刪除的記錄,InnoDB存儲引擎 會記錄 其FTS Document ID, 并將其保存在DELETED auxiliary table中 。 在設(shè)置參數(shù)innodb_ft_ aux_ table后, 用戶同樣可以訪問information_schema架構(gòu)下的表 INNODB_FT_DELETED來觀察刪除的FTS Document ID。

由于文檔的DML操作實際并不刪除索引中的數(shù)據(jù),相反還會在對應(yīng)的DELETED表中 插入 記錄,因此隨著應(yīng) 用程序的允許,索引 會變得非常大,即使索引中的有些數(shù)據(jù) 已經(jīng)被刪除,查詢也不會選擇這類記錄。 為此,InnoDB存儲引擎提供了一種方式, 允許用戶手工地將已經(jīng)刪除的記錄從索引中徹底刪除, 該命令就是OPTIMIZE TABLE。?

當前l(fā)nnoDB存儲引擎的全文檢索還存在以下的限制:

1每張表只能有一個全文檢索的索引 。

2由多列組合而成的全文檢索的索引列必須使用相同的字符集與排序規(guī)則。

3不支持沒有單詞界定符(delimiter)的語言, 如中文、 日語、 韓語等。

5.8.4 全文檢索

? ??????MySQL數(shù)據(jù)庫支持全文檢索(Full-Text Search)的查詢,MySQL數(shù)據(jù)庫通過MATCH()…AGAINST()語法支持全文檢索的查詢, MATCH指定了需要被查詢的列, AGAINST指定了使用何種方法去進行查詢。 下面將對各種查詢模式進行詳細的介紹。

1. Natural Language

????????全文檢索通過MATCH函數(shù)進行查詢, 默認采用Natural Language 模式, 其表示查詢帶有指定word 的文檔。

? ??????在WHERE條件中使用MATCH函數(shù),查詢返回的結(jié)果是根據(jù)相關(guān)性(Relevance)進行降序排序的,即相關(guān)性最高的結(jié)果放在第一位。相關(guān)性的值是一個非負的浮點數(shù)字,0表示沒有任何的相關(guān)性。根據(jù)MySQL官方的文檔可知,其相關(guān)性的計算依據(jù)以下四個條件:

1 word是否在文檔中出現(xiàn)。

2 word在文檔中出現(xiàn)的次數(shù)。

3 word在索引列中的數(shù)量。

4 多少個文檔包含該word。

2.Boolean

? ??????MySQL數(shù)據(jù)庫允許使用IN BOOLEAN MODE修飾符來進行全文檢索。 當使用該修飾符時, 查詢字符串的前后字符會有特殊的含義.

+表示該word必須存在。

-表示該word必須被排除。

(no operator)表示該word是可選的,但是如果出現(xiàn),其相關(guān)性會更高

@distance表示查詢的多個單詞之間的距離是否在distance之內(nèi),distance的單位是字節(jié)。這種全文檢索的查詢也稱為ProximitySearch。如MATCH(body) AGAINST ("'Pease pot"@30'IN BOOLEAN MODE)表示字符串Pease和pot之間的距離需在30字節(jié)內(nèi)。

>表示出現(xiàn)該單詞時增加相關(guān)性。

<表示出現(xiàn)該單詞時降低相關(guān)性。

~ 表示允許出現(xiàn)該單詞,但是出現(xiàn)時相關(guān)性為負(全文檢索查詢允許負相關(guān)性)。

*表示以該單詞開頭的單詞,如lik*,表示可以是lik、like,又或者likes。

"表示短語。

3. Query Expansion

? ??????MySQL數(shù)據(jù)庫還支持全文檢索的擴展查詢。 這種查詢通常在查詢的關(guān)鍵詞太短, 用戶需要implied knowledge (隱含知識)時進行。 例如, 對于單詞database的查詢, 用戶可能希望查詢的不僅僅是包含database的文檔, 可能還指那些包含MySQL、 Oracle、 D82、 RDBMS的單詞。 而這時可以使用Query Expansion模式來開啟全文檢索的 implied knowledge。

????????通過在查詢短語中添加WITH QUERY EXPANSION或IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION可以開啟 blind query expansion (又稱為automatic relevance feedback)。 該查詢分為兩個階段。

第一階段:根據(jù)搜索的單詞進行全文索引查詢。

第二階段:根據(jù)第一階段產(chǎn)生的分詞再進行 次全文檢索的查詢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 捐款本來是一件大家奉獻愛心的好事,可是當捐款變?yōu)楸凭钑r,愛心還會在嗎? 近日,在廣東茂名茂南區(qū)一間叫朝陽學(xué)校的民辦...
    真大或小閱讀 275評論 0 1
  • 什么是1:1會議?就是從你說改為她說,運用25:25:50的方法少問,少說,多聽。 為什么有時候員工心里有無數(shù)...
    合肥李風(fēng)麗閱讀 184評論 0 0
  • 咸菜,小時候的回想。 小時候,生活不富裕卻很幸福,什么都是好的,值得回味的。當我們長大了,成家了,最想念的還是媽媽...
    上善若水的閱讀日閱讀 402評論 0 0

友情鏈接更多精彩內(nèi)容