Phoenix是什麼?看看官網就知道了,我就不細說了。關於它的優點,官網也是列了一大堆,我也不復述了。
下面只談談截止Phoenix4.2.1,我認爲初學者應該注意的兩個特徵:
1. 完全喪失了HBase的多版本特徵
HBases至少也是三維結構(row、cf:cq、timestamp)的數據模型,Phoenix將其映射爲二維的關係模型後,便面對着損失信息精度的尷尬場面。這種尷尬具體表現在Phoenix使用的兩個方面:
a. 不能爲一個cell指定任意的timestamp
作爲HBase的第三維特徵,timestamp的重要性不言而喻。由於絕大部分數據應用場景都離不開時間維度,所以我們經常會將數據中的某個時間字段映射到timestamp,也就無需在CF中存儲該字段了。這樣的好處是:既節約了存儲空間,也可以使用timestamp相關的API(例如Get#setTimeRange)進行查詢。遺憾的是,Phoenix並不能讓我們像HBase一樣指定任意的timestamp。雖然Phoenix在F.A.Q.中煞有其事的提出了貌似這個問題的解決方案。但是深究之後你會發現這是一個比較坑爹的方案。理由如下:
- 首先,該方案貌似可以指定任意的timestamp,但是需要在應用程序中頻繁的創建和關閉Connection,雖然他們還專門強調這不是一個“昂貴”的操作(is not an expensive operation),但是這樣的代碼風格估計會讓很多人無語。
- 其次,該方案的任意timestamp其實是有條件的,即必須大於表的創建時間,否則,會出現“Table undefined”的異常。
CREATE INDEX idx_name ON TAB_NAME(IDX_FIELD);
SELECT OtherField FROM TAB_NAME WHERR IDX_FIELD='';
我以爲這樣就可以利用索引了,但是其實不然,必須要CREATE INDEX idx_name ON TAB_NAME(IDX_FIELD) INCLUDE(OtherField);
因爲二級索引創建了一個新的索引表,沒有INICLUDE時,索引表中的value爲空,上述查詢將不會利用索引表,而是Full Scan主表。INCLUDE時,會將OtherField字段寫入索引表的value中,上述查詢將會利用索引表進行Range Sacn。這種做法讓人不得不吐糟,雖然說存儲不值錢,但是也不能這麼浪費吧。
不過細想一下,這也是Phoenix的無奈之舉:因爲它不能保證主表和索引表對應Region的本地化,所以也就無法根據索引表的結果再去查主表了。
變通方案
a. 客戶端自己解決:先查索引表獲取Primary Key,然後根據Primary Key二次查詢主表;
b. 使用其他索引方案......
針對目前Phoenix的二級索引方案,我個人建議一定要謹慎使用。鑑於其無與倫比的膨脹性,我建議只考慮使用在比較小的表上,並且對該表是寫少讀多。