1. 程式人生 > >讓Hive支援行級insert、update、delete

讓Hive支援行級insert、update、delete

Hive從0.14版本開始支援事務和行級更新,但預設是不支援的,需要一些附加的配置。要想支援行級insert、update、delete,需要配置Hive支援事務。

一、Hive具有ACID語義事務的使用場景
1. 流式接收資料。
許多使用者使用諸如Apache Flume、Apache Storm或Apache Kafka這樣的工具將流資料灌入Hadoop叢集。當這些工具以每秒數百行的頻率寫入時,Hive也許只能每15分鐘到1小時新增一個分割槽,因為過於頻繁地新增分割槽很快就會使一個表中的分割槽數量難以維護。而且這些工具還可能向已存在的分割槽中寫資料,但是這樣將會產生髒讀(可能讀到查詢開始時間點以後寫入的資料),還在這些分割槽的所在目錄中遺留大量小檔案,進而給NameNode造成壓力。在這個使用場景下,事務支援可以獲得資料的一致性檢視同時避免產生過多的檔案。

2. 緩慢變化維。
在一個典型的星型模式資料倉庫中,維度表隨時間的變化很緩慢。例如,一個零售商開了一家新商店,需要將新店資料加到商店表,或者一個已有商店的營業面積或其它需要跟蹤的特性改變了。這些改變會導致插入或修改個別記錄。從0.14版本開始,Hive支援行級更新。

3. 資料重述。
有時發現數據集合有錯誤並需要更正。或者當前資料只是個近似值(如只有全部資料的90%,得到全部資料會滯後)。或者業務業務規則可能需要根據後續事務重述特定事務(打個比方,一個客戶購買了一些商品後又購買了一個會員資格,此時可以享受折扣價格,包括先前購買的商品)。或者一個客戶可能按照合同在終止了合作關係後要求刪除他們的客戶資料。從Hive 0.14開始,這些使用場景可以通過INSERT、UPDATE和DELETE支援。

二、配置Hive支援事務(Hive 2.0版)

1. 在hive-site.xml檔案中新增如下配置項
<property>
    <name>hive.support.concurrency</name>
    <value>true</value>
</property>
<property>
    <name>hive.exec.dynamic.partition.mode</name>
    <value>nonstrict</value>
</property>
<property>
    <name>hive.txn.manager</name>
    <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
<property>
    <name>hive.compactor.initiator.on</name>
    <value>true</value>
</property>
<property>
    <name>hive.compactor.worker.threads</name>
    <value>1</value>
</property>

2. 新增Hive元資料(使用mysql儲存)
INSERT INTO NEXT_LOCK_ID VALUES(1);
INSERT INTO NEXT_COMPACTION_QUEUE_ID VALUES(1);
INSERT INTO NEXT_TXN_ID VALUES(1);
COMMIT;
說明:初始時這三個表沒有資料,如果不新增資料,會報以下錯誤:
org.apache.hadoop.hive.ql.lockmgr.DbTxnManager FAILED: Error in acquiring locks: Error communicating with the metastore

三、測試

1. 啟動hadoop叢集和mysql
$HADOOP_HOME/sbin/start-dfs.sh
$HADOOP_HOME/sbin/start-yarn.sh
~/mysql/bin/mysqld &

2. 建立測試表
use test;
create table t1(id int, name string) 
clustered by (id) into 8 buckets 
stored as orc TBLPROPERTIES ('transactional'='true');
說明:建表語句必須帶有into buckets子句和stored as orc TBLPROPERTIES ('transactional'='true')子句,並且不能帶有sorted by子句。

3. 測試insert、update、delete
insert into t1 values (1,'aaa');
insert into t1 values (2,'bbb');
update t1 set name='ccc' where id=1;
delete from t1 where id=2; 
執行結果分別如圖1-3所示。


圖1


圖2


圖3
說明:不能修改bucket列的值,否則會報以下錯誤:
FAILED: SemanticException [Error 10302]: Updating values of bucketing columns is not supported.  Column id.

4. 已有非ORC表的轉換
-- 在本地檔案/home/grid/a.txt中寫入以下4行資料
1,張三,US,CA
2,李四,US,CB
3,王五,CA,BB
4,趙六,CA,BC

-- 建立非分割槽表並載入資料
CREATE TABLE t1 (id INT, name STRING, cty STRING, st STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';  
LOAD DATA LOCAL INPATH '/home/grid/a.txt' INTO TABLE t1;  
SELECT * FROM t1;

-- 建立外部分割槽事務表並載入資料
CREATE EXTERNAL TABLE t2 (id INT, name STRING) PARTITIONED BY (country STRING, state STRING)
CLUSTERED BY (id) INTO 8 BUCKETS
STORED AS ORC TBLPROPERTIES ('transactional'='true');
INSERT INTO T2 PARTITION (country, state) SELECT * FROM T1;
SELECT * FROM t2;

-- 修改資料
INSERT INTO TABLE t2 PARTITION (country, state) VALUES (5,'劉','DD','DD');
UPDATE t2 SET name='張' WHERE id=1;
DELETE FROM t2 WHERE name='李四';
SELECT * FROM t2; 
修改前和修改後的資料分別如圖4、圖5所示。

圖4

圖5
說明:不能update分割槽鍵,否則會報以下錯誤:
FAILED: SemanticException [Error 10292]: Updating values of partition columns is not supported
四、參考
https://cwiki.apache.org/confluence/display/Hive/Hive+Transactions
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML#LanguageManualDML-Delete
http://unmeshasreeveni.blogspot.in/2014/11/updatedeleteinsert-in-hive-0140.html
https://www.mapr.com/blog/hive-transaction-feature-hive-10