Åtgärda ett fel om att Apache Hive har slut på minne i Azure HDInsight
Lär dig hur du åtgärdar ett OOM-fel (Apache Hive out of memory) när du bearbetar stora tabeller genom att konfigurera Hive-minnesinställningar.
Köra Apache Hive-fråga mot stora tabeller
En kund körde en Hive-fråga:
SELECT
COUNT (T1.COLUMN1) as DisplayColumn1,
…
…
….
FROM
TABLE1 T1,
TABLE2 T2,
TABLE3 T3,
TABLE5 T4,
TABLE6 T5,
TABLE7 T6
where (T1.KEY1 = T2.KEY1….
…
…
Några nyanser i den här frågan:
- T1 är ett alias för en stor tabell, TABLE1, som har många STRING-kolumntyper.
- Andra tabeller är inte så stora men har många kolumner.
- Alla tabeller ansluter varandra, i vissa fall med flera kolumner i TABLE1 och andra.
Hive-frågan tog 26 minuter att slutföra på ett A3 HDInsight-kluster med 24 noder. Kunden märkte följande varningsmeddelanden:
Warning: Map Join MAPJOIN[428][bigTable=?] in task 'Stage-21:MAPRED' is a cross product
Warning: Shuffle Join JOIN[8][tables = [t1933775, t1932766]] in Stage 'Stage-4:MAPRED' is a cross product
Genom att använda Apache Tez-körningsmotorn. Samma fråga kördes i 15 minuter och utlöste sedan följande fel:
Status: Failed
Vertex failed, vertexName=Map 5, vertexId=vertex_1443634917922_0008_1_05, diagnostics=[Task failed, taskId=task_1443634917922_0008_1_05_000006, diagnostics=[TaskAttempt 0 failed, info=[Error: Failure while running task:java.lang.RuntimeException: java.lang.OutOfMemoryError: Java heap space
at
org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:172)
at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:138)
at
org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:324)
at
org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable$1.run(TezTaskRunner.java:176)
at
org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable$1.run(TezTaskRunner.java:168)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1628)
at
org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable.call(TezTaskRunner.java:168)
at
org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable.call(TezTaskRunner.java:163)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.OutOfMemoryError: Java heap space
Felet kvarstår när du använder en större virtuell dator (till exempel D12).
Felsöka felet slut på minne
Våra support- och teknikteam upptäckte tillsammans att ett av problemen som orsakade felet med slut på minne var ett känt problem som beskrivs i Apache JIRA:
"När hive.auto.convert.join.noconditionaltask = true kontrollerar vi noconditionaltask.size och om summan av tabellstorlekarna i kartkopplingen är mindre än noconditionaltask.size skulle planen generera en kartkoppling, Problemet med detta är att beräkningen inte tar hänsyn till de omkostnader som introduceras av en annan HashTable-implementering som resultat om summan av indatastorlekarna är mindre än noconditionaltask-storleken genom att en liten marginalfråga träffar OOM."
Hive.auto.convert.join.noconditionaltask i filen hive-site.xml har angetts till true:
<property>
<name>hive.auto.convert.join.noconditionaltask</name>
<value>true</value>
<description>
Whether Hive enables the optimization about converting common join into mapjoin based on the input file size.
If this parameter is on, and the sum of size for n-1 of the tables/partitions for a n-way join is smaller than the
specified size, the join is directly converted to a mapjoin (there is no conditional task).
</description>
</property>
Det är troligt att map join var orsaken till Java Heap Space out of memory-felet. Som förklaras i blogginlägget Hadoop Yarn minnesinställningar i HDInsight, när Tez-körningsmotorn använde heaputrymmet som faktiskt används tillhör Tez-containern. Se följande bild som beskriver Tez-containerminnet.
Som blogginlägget antyder definierar följande två minnesinställningar containerminnet för heapen: hive.tez.container.size och hive.tez.java.opts. Av vår erfarenhet innebär undantaget slut på minne inte att containerstorleken är för liten. Det innebär att Java-heapstorleken (hive.tez.java.opts) är för liten. Så när du ser slut på minne kan du försöka öka hive.tez.java.opts. Om det behövs kan du behöva öka hive.tez.container.size. Inställningen java.opts bör vara cirka 80 % av container.size.
Kommentar
Inställningen hive.tez.java.opts måste alltid vara mindre än hive.tez.container.size.
Eftersom en D12-dator har 28 GB minne bestämde vi oss för att använda en containerstorlek på 10 GB (1 0240 MB) och tilldela 80 % till java.opts:
SET hive.tez.container.size=10240
SET hive.tez.java.opts=-Xmx8192m
Med de nya inställningarna kördes frågan på under 10 minuter.
Nästa steg
Att få ett OOM-fel betyder inte nödvändigtvis att containerstorleken är för liten. I stället bör du konfigurera minnesinställningarna så att heapstorleken ökar och är minst 80 % av containerminnets storlek. Information om hur du optimerar Hive-frågor finns i Optimera Apache Hive-frågor för Apache Hadoop i HDInsight.