我知道Hive / Hadoop不是要更新/删除,但我的要求是根据表person21的数据更新表person20。随着Hive和ORC的进步,它支持ACID,但看起来还不成熟。
$ hive --version
hive 1.1.0-cdh5.6.0
以下是我为测试更新逻辑而执行的详细步骤。
CREATE TABLE person20(
persid int,
lastname string,
firstname string)
CLUSTERED BY (
persid)
INTO 1 BUCKETS
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.orc.OrcSerde'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION
'hdfs://hostname.com:8020/user/hive/warehouse/person20'
TBLPROPERTIES (
'COLUMN_STATS_ACCURATE'='true',
'numFiles'='3',
'numRows'='2',
'rawDataSize'='348',
'totalSize'='1730',
'transactional'='true',
'transient_lastDdlTime'='1489668385')
插入语句:
INSERT INTO TABLE person20 VALUES (0,'PP','B'),(2,'X','Y');
选择语句:
set hive.cli.print.header=true;
select * from person20;
persid lastname firstname
2 X Y
0 PP B
我有另一个表是person20的副本,即person21:
CREATE TABLE person21(
persid int,
lastname string,
firstname string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://hostname.com:8020/user/hive/warehouse/person21'
TBLPROPERTIES (
'COLUMN_STATS_ACCURATE'='true',
'numFiles'='1',
'numRows'='2',
'rawDataSize'='11',
'totalSize'='13',
'transient_lastDdlTime'='1489668344')
插入语句:
INSERT INTO TABLE person20 VALUES (0,'SS','B'),(2,'X','Y');
选择语句:
select * from person21;
persid lastname firstname
2 X1 Y
0 SS B
我想实现MERGE逻辑:
Merge into person20 p20 USING person21 p21
ON (p20.persid=p21.persid)
WHEN MATCHED THEN
UPDATE set p20.lastname=p21.lastname
从Hive 2.2开始将提供此功能。
其他选项是相关子查询更新:
hive -e "set hive.auto.convert.join.noconditionaltask.size = 10000000; set hive.support.concurrency = true; set hive.enforce.bucketing = true; set hive.exec.dynamic.partition.mode = nonstrict; set hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; set hive.compactor.initiator.on = true;
set hive.compactor.worker.threads = 1 ; UPDATE person20 SET lastname = (select lastname from person21 where person21.lastname=person20.lastname);"
我认为它不支持子查询。相同的语句适用于常量。
hive -e "set hive.auto.convert.join.noconditionaltask.size = 10000000; set hive.support.concurrency = true; set hive.enforce.bucketing = true; set hive.exec.dynamic.partition.mode = nonstrict; set hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; set hive.compactor.initiator.on = true;
set hive.compactor.worker.threads = 1 ; UPDATE person20 SET lastname = 'PP' WHERE persid = 0;"
-此语句成功更新了记录。
您能否帮助我找到在HIVE中执行DML /合并操作的最佳策略。
最佳答案
您可以通过蛮力做到这一点:
person20
,但不创建ACID,在虚拟col名称上进行分区,并为“dummy” person20
和person21
tmpperson20
,其结构与person20
完全相同,并且具有相同的“虚拟”分区INSERT INTO tmpperson20 PARTITION (dummy='dummy') SELECT p20.persid, p21.lastname, ... FROM person20 p20 JOIN person21 p21 ON p20.persid=p21.persid
INSERT INTO tmpperson20 PARTITION (dummy='dummy') SELECT * FROM person20 p20 WHERE NOT EXISTS (select p21.persid FROM person21 p21 WHERE p20.persid=p21.persid)
ALTER TABLE person20 DROP PARTITION (dummy='dummy')
ALTER TABLE person20 EXCHANGE PARTITION (dummy='dummy') WITH tmpperson20
tmpperson20
但是由于存储,使用ACID表可能会更加棘手。
您也可以尝试使用在游标上迭代并在循环中应用单个UPDATE的过程语言。低效率的大量更新...
Hive 2.x附带了HPL/SQL实用程序,它可能已安装在Hive 1.x之上,但是我从来没有机会尝试过。 Oracle方言对Hive感到很奇怪...!
或者,您可以在循环中使用JDBC
ResultSet
和PreparedStatement
开发一些自定义Java代码。