Vespa 裡面支援了許多資料型態(data type),包括 int、long、byte、double、boolean、string、struct(物件)、collection(例如 array、weighted set)等等,可以參考官方文件 [1],這些資料型態最主要的影響在於存放時所消耗的空間大小。而關於使用時的使用模式,則主要是來自於設定的索引型態(index type)來決定。
索引型態
索引型態主要分為 attribute 和 index 兩種。概略來說,可以直接把它們看成是「存放在記憶體」和「存放在硬碟」的差別。在 Vespa 的設計裡,好像基本上會假定字串以外的型態都放在 attribute 比較好的樣子,因為如果要以資料欄位作為像是排序的依據的話,資料欄位必須要是 attribute index 才行。
attribute
attribute 的欄位都會被存放在記憶體裡,意味著其實如果可以的話,最好不要把長度無法預測的資料欄位設定為 attribute,因為這樣會導致身為稀缺資源的記憶體被大量耗用在存放這些字串。不過實際運作時,因為 OS 會有虛擬記憶體的概念,因此不一定會真的完全保證 attribute 的欄位就一定是被放在記憶體上,如果想要確保這件事,首先就得確保 OS 不會使用到虛擬記憶體。
設定為 attribute 的欄位,就能夠執行以下的這些操作:
- grouping
- sorting
- word-match search
- numerical search
- prefix search
- ranking functions
- document summaries
- document reference
在對 attribute 的欄位做搜尋的時候,原則上 Vespa 只會做線性搜尋,只是因為搜尋時是對記憶體內的資料做,所以一般狀況下效率不會太差。但當有必要的時候,對 attribute 欄位設定 fast-search 可能是蠻重要的事情,這會讓 Vespa 對該欄位建立 B-tree 索引,就像在 RDBMS 上對欄位建索引一樣。到這裡,某種程度上可以感覺到 Vespa 對這種基本型態的處理其實算是比較粗糙的,效能很大程度是直接依賴「資料放在記憶體上」的這件事。所以如果沒有要做什麼比較複雜的排序或計算之類的話,基本資料的儲存並不是 Vespa 的強項,把資料放在 RDBMS 裡可能可以獲得相差不遠的效率但大幅下降的維運成本。
index
index 的欄位是存放在硬碟中的 [2-3],代表資料被定義為 index 的話,儲存成本相較於 attribute 會比較低,但同時存取速度也會比較慢。index 欄位只能用在字串上(這又突顯了 Vespa 對於基本型態的處理比較粗糙的事實),除了存放位置以外,index 跟 attribute 最大的不同就是 index 的欄位都會做 normalization 和 tokenization [3]。換言之,index 主要(唯一?)的使用情境是在於做各種字串處理或者字串搜尋。
Search Definition 的定義
在 Search Definition 上定義資料的索引型態時,attribute 和 index 並非是只能設定其中一個,其實可以同時設定兩個,只是同時設定時有個有點有趣的小細節。因為索引型態是透過 pipe 連接起來的,pipe 連接的意思就是會依序執行,所以它的結果會很像是使用 Java 8 的 stream API 那樣。舉例來說,如果我對某個欄位設定 indexing: index | attribute,這表示的是這個欄位的資料會先進行 index,在這個過程中會被 tokenize 等等,接著被 tokenized 的資料再送去 attribute 做索引!換言之,在一般狀況下如果我們想要同時設定 attribute 跟 index,通常我們應該會想設定 indexing: attribute | index,而不太會是反過來放的狀況。同時,當我們設定 indexing: attribute | index 時,Vespa 的搜尋會去搜尋 index 而不會搜尋 attribute [4]。(不過這樣的話那幹麻要支援同時寫 attribute 和 index 呀….?)