일반 설정으로는 Hive에서 update 쿼리를 처리할 수 없다.
왜냐하면 Hive는 애초에 update & delete 등 데이터의 변화를 고려하지 않고 설계되었기 때문이다.
이것에 대한 설명은 나중에 따로 포스팅을 작성할 예정이다.
아무튼 ACID를 적용하면 UPDATE & DELETE 쿼리를 할 수 있다.
최근에 쿼리를 작성하다가. 해당 에러 때문에 구글링하는데 시간소비를 굉장히 오래했다.
[에러내용]
SQL Error [500051] [HY000]: [Cloudera][HiveJDBCDriver](500051) ERROR processing query/statement. Error Code: 2, SQL state: Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.tez.TezTask. Vertex failed, vertexName=Map 1, vertexId=vertex_1655118886583_0438_1_01, diagnostics=[Task failed, taskId=task_1655118886583_0438_1_01_000000, diagnostics=[TaskAttempt 0 failed, info=[Error: Error while running task ( failure ) : attempt_1655118886583_0438_1_01_000000_0:java.lang.RuntimeException: java.lang.RuntimeException: Map operator initialization failed
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:296)
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:250)
at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:374)
at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:73)
at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:61)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1729)
at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:61)
at org.apache.tez.runtime.task.TaskRunner2Callable.callInternal(TaskRunner2Callable.java:37)
at org.apache.tez.common.CallableWithNdc.call(CallableWithNdc.java:36)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:108)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:41)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:77)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.RuntimeException: Map operator initialization failed
at org.apache.hadoop.hive.ql.exec.tez.MapRecordProcessor.init(MapRecordProcessor.java:354)
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:266)
... 16 more
Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: Unexpected column vector type STRUCT
at org.apache.hadoop.hive.ql.exec.vector.VectorCopyRow.init(VectorCopyRow.java:302)
at org.apache.hadoop.hive.ql.exec.vector.mapjoin.VectorMapJoinCommonOperator.initializeOp(VectorMapJoinCommonOperator.java:419)
at org.apache.hadoop.hive.ql.exec.vector.mapjoin.VectorMapJoinGenerateResultOperator.initializeOp(VectorMapJoinGenerateResultOperator.java:115)
at org.apache.hadoop.hive.ql.exec.Operator.initialize(Operator.java:376)
at org.apache.hadoop.hive.ql.exec.Operator.initialize(Operator.java:573)
at org.apache.hadoop.hive.ql.exec.Operator.initializeChildren(Operator.java:525)
at org.apache.hadoop.hive.ql.exec.Operator.initialize(Operator.java:386)
at org.apache.hadoop.hive.ql.exec.tez.MapRecordProcessor.init(MapRecordProcessor.java:335)
... 17 more
], TaskAttempt 1 failed, info=[Error: Error while running task ( failure ) : attempt_1655118886583_0438_1_01_000000_1:java.lang.RuntimeException: java.lang.RuntimeException: Map operator initialization failed
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:296)
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:250)
at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:374)
at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:73)
at org.apache.tez.runtime.task.TaskRunner2Callable$1.run(TaskRunner2Callable.java:61)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
에러 내용이 굉장히 길지만, 계속 반복되어 밑 부분은 잘랐다.
이 에러가 발생하게된 원인은 UPDATE 에서 문제가 있었다.
UPDATE CompanyA.employee
SET city='seoul'
WHERE employee_id IN (SELECT employee_id from CompanyB.employee_list)
AND city='busan'
예를 들어서 만든 쿼리이다. 전체적인 흐름은 똑같다.
WHERE IN으로 서브쿼리를 넣고, UPDATE를 진행할 때만 이 에러가 발생했다.
여기서 신기한 점은 이 쿼리를 조금 전환하여
UPDATE CompanyA.employee
SET city='seoul'
WHERE employee_id IN ('AAA','BBB')
AND city='busan'
이렇게 서브쿼리를 안하거나
혹은
SELECT *
FROM CompanyA.employee
WHERE employee_id IN (SELECT employee_id from CompanyB.employee_list)
AND city='busan'
똑같은 쿼리로 UPDATE를 안하면 에러없이 잘 수행이 된다.
이 에러에 대해 구글링한 결과HIVE Map join option 때문에 발생한 오류였다.
Map join 은 HIVE의 쿼리 속도를 향상시켜주는 옵션이라서 보통 Default 값으로 true가 되어있다.
원래 join 작업은 Map/Reduce 단계를 거쳐야되지만, 이 옵션을 이용하면 Map/Reduce 단계를 거치지 않고, mapper 내에서 join하여 table을 로드할 수 있다고 한다.
여기도 default 값으로 true가 들어가 있어서 join을 할 때 강제로 맵조인이 활성화되었고,
설정된 메모리 값보다 join할려고 하는 테이블의 값이 커서 발생하는 오류로 판단된다.
그래서
set hive.auto.convert.join = false;
이 옵션으로 맵조인을 false로 바꾸면 에러 없이 잘 된다.