Phoenix系列:原子的Upsert

Phoenix系列:原子的Upsert

Phoenix的插入語句是Upsert,Update和Insert的組合語義。即,如果數據表中沒有這條記錄那麼插入這條記錄,如果有則更新。判斷是否存在相同的數據是使用ON DUPLICATE KEY來驗證的,這裏的KEY就是建表時候的主鍵(PRIMARY KEY)。和Oracle的Merge Into以及MySQL的Insert …on duplicate key 是類似的功能。ON DUPLICATE KEY這個語法要到Phoenix 4.9之後纔有。這個功能把HBase的Increment和CheckAndPut兩個原子操作合在了一起。當Upsert語句被提交到服務端的時候,所要更新的行會被lock住,同時相關的列會被讀取,ON DUPLICATE KEY語句會被執行。由於會鎖住所在的行,所以會有一些性能損耗,但是這個損耗比較小,類似於HBase中Put和CheckAndPut的之間的性能差異。

由於有了ON DUPLICATE KEY分句,如果行存在,那麼VALUES後面的值將會爲忽略。在ON DUPLICATE KEY後面還有其他的語法來實現不同的功能:

如果分句是ON DUPLICATE KEY IGNORE 的話,那麼這行就不會被Update。
如果分句是ON DUPLICATE KEY UPDATE 的話,行就會被後面的Update語句更新,這個更新是獲取了行級鎖的。
如果操作同一行的多個Upsert在同一時間被批量提交的話,服務端將會按順序執行它們。所以無論自動提交是開還是關,都會得到一樣的結果。

下面列出了UPSERT的一些常用語法:

UPSERT INTO TEST VALUES('foo','bar',3); 
UPSERT INTO TEST(NAME,ID) VALUES('foo',123); 
UPSERT INTO TEST(ID, COUNTER) VALUES(123, 0) ON DUPLICATE KEY UPDATE COUNTER = COUNTER + 1; 
UPSERT INTO TEST(ID, MY_COL) VALUES(123, 0) ON DUPLICATE KEY IGNORE;

如果是4.9之前的版本的話,ON DUPLICATE KEY 分句是不存在的。只有上例的第一和第二種語法。如果原表中有數據重複的話,就會直接更新。

和Oracle和MySQL一樣,Phoenix也有Upsert Select語法。插入或更新的數據是另外一個查詢結果集。插入或更新的列和查詢結果集的列要一一匹配,如果不顯式的列出列,那麼查詢結果集的列要和目標表的列的元數據保持順序一致。如果auto commit開啓的話,會在服務端就提交了,否則會緩存到客戶端,等着顯式提交的時候進行批量upsert。自動提交的話,可以通過客戶端配置“phoenix.mutate.upsertBatchSize”指定大小,默認10000行/次。

示例語法如下:

UPSERT INTO test.targetTable(col1, col2) SELECT col3, col4 FROM test.sourceTable WHERE col5 < 100 
UPSERT INTO foo SELECT * FROM bar;

最後,來說一下ON DUPLICATE KEY的一些限制。

  1. 主鍵不會被更新,它是創建新行的基礎。

  2. 事務表不應該使用這個功能,因爲當衝突發生時,原子的Upsert操作有可能已經被異常處理掉了。

  3. 不可變表不應該使用這個功能,因爲不應該有數據更新不可變表。

  4. 如果要使用這個子句,在連接時,就不能設置CURRENT_SCN屬性,因爲除非最新的值正在被更新,否則HBase的操作不是原子的。

  5. 同一列在同一句語句中不應該被更新超過一次。

  6. ON DUPLICATE KEY 子句中不能有聚合或者序列。

  7. 雖然在列上的全局索引是支持原子化的更細你的,但是還是不推薦在全局索引表上使用這個子語句。因爲當維護二級索引的時候,行會被鎖定,這個子句胡產生一個RPC調用。

參考地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章