Az Apache Hive memóriahiány miatti hibáinak kijavítása az Azure HDInsightban

Megtudhatja, hogyan háríthatja el az Apache Hive memóriahiányos (OOM) hibáit nagy méretű táblák feldolgozásakor a Hive memóriabeállításainak konfigurálásával.

Apache Hive-lekérdezés futtatása nagy táblákon

Egy ügyfél Hive-lekérdezést futtatott:

SELECT
    COUNT (T1.COLUMN1) as DisplayColumn1,
    …
    …
    ….
FROM
    TABLE1 T1,
    TABLE2 T2,
    TABLE3 T3,
    TABLE5 T4,
    TABLE6 T5,
    TABLE7 T6
where (T1.KEY1 = T2.KEY1….
    …
    …

A lekérdezés néhány árnyalata:

  • A T1 egy nagy tábla, a TABLE1 aliasa, amely számos STRING oszloptípussal rendelkezik.
  • A többi tábla nem olyan nagy, de sok oszlopot tartalmaz.
  • Minden tábla csatlakozik egymáshoz, egyes esetekben több oszlopot tartalmaz a TABLE1 és mások.

A Hive-lekérdezés 26 percet vett igénybe egy 24 csomópontos A3 HDInsight-fürtön. Az ügyfél a következő figyelmeztető üzeneteket észlelte:

    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

Az Apache Tez végrehajtási motor használatával. Ugyanez a lekérdezés 15 percig futott, majd a következő hibát eredményezte:

    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

A hiba nagyobb virtuális gép (például D12) használatakor is fennáll.

Memóriakimaradási hiba hiba elhárítása

Támogatási és mérnöki csapataink közösen megállapították, hogy a memóriakimaradást okozó problémák egyike az Apache JIRA-ban leírt ismert probléma:

"Ha hive.auto.convert.join.noconditionaltask = true, ellenőrizzük a noconditionaltask.size értéket, és ha a térképillesztésben a táblaméretek összege kisebb, mint a noconditionaltask.size, akkor a terv térképcsatlakozást hozna létre, a probléma az, hogy a számítás nem veszi figyelembe a különböző HashTable-implementáció által okozott többletterhelést eredményként, ha a bemeneti méretek összege kisebb, mint a noconditionaltask mérete egy kis margólekérdezés által, eléri az OOM-t."

A hive-site.xml fájlban lévő hive.auto.convert.join.noconditionaltaskértéke igaz:

<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>

Valószínű, hogy a térképcsatlakozás okozta a Java-tárterület memóriakimaradási hibáját. Amint azt a HDInsightban a Hadoop Yarn memóriabeállításai című blogbejegyzés ismerteti, a Tez végrehajtási motor használata esetén a felhasznált tárterület valójában a Tez-tárolóhoz tartozik. Tekintse meg a Tez tárolómemóriát ismertető alábbi képet.

Tez tárolómemória-diagramja: Hive memóriahiba

Ahogy a blogbejegyzés is sugallja, a következő két memóriabeállítás határozza meg a tárolómemóriát a heaphoz: hive.tez.container.size és hive.tez.java.opts. Tapasztalatunk szerint a memóriakivétel nem jelenti azt, hogy a tároló mérete túl kicsi. Ez azt jelenti, hogy a Java-heap mérete (hive.tez.java.opts) túl kicsi. Így amikor kevés a memória, megpróbálhatja növelni a hive.tez.java.opts fájlt. Szükség esetén előfordulhat, hogy növelnie kell a hive.tez.container.size értéket. A java.opts beállításnak a container.size körülbelül 80%-ának kell lennie.

Megjegyzés

A hive.tez.java.opts beállításnak mindig kisebbnek kell lennie, mint a hive.tez.container.size.

Mivel egy D12-gép 28 GB memóriával rendelkezik, úgy döntöttünk, hogy 10 GB-os tárolóméretet (10240 MB) használunk, és 80%-ot rendelünk hozzá a java.opts szolgáltatáshoz:

SET hive.tez.container.size=10240
SET hive.tez.java.opts=-Xmx8192m

Az új beállításokkal a lekérdezés 10 perc alatt sikeresen lefutott.

Következő lépések

Az OOM-hiba nem feltétlenül jelenti azt, hogy a tároló mérete túl kicsi. Ehelyett úgy kell konfigurálnia a memóriabeállításokat, hogy a heap mérete növekedjen, és a tároló memóriaméretének legalább 80%-a legyen. A Hive-lekérdezések optimalizálásához lásd: Apache Hive-lekérdezések optimalizálása az Apache Hadoophoz a HDInsightban.