2016-07-19 28 views
0

Ich erhalte einen java.lang.OutOfMemoryError: GC Overhead-Limit in Hive überschritten. Bei der Suche habe ich festgestellt, dass 98% aller CPU-Zeit des Prozesses auf Müll sammeln geht (was auch immer das bedeutet?). Ist der Kern meines Problems in meiner Abfrage? Sollte ich das unten auf eine andere Weise schreiben, um diese Art von Problem zu vermeiden?Effizientere Abfrage zur Vermeidung von OutOfMemoryError in Hive

Ich versuche zu zählen, wie viele von einem bestimmten Telefontyp eine aktive 'Use' in einem bestimmten Zeitraum haben. Gibt es einen Weg, diese Logik anders zu machen, würde das besser laufen?

select count(a.imei) 
from 
(Select distinct imei 
from pingdata 
where timestamp between TO_DATE("2016-06-01") AND TO_DATE("2016-07-17") 
and ((SUBSTR(imei,12,2) = "04") or (SUBSTR(imei,12,2) = "05"))) a 
join 
(SELECT distinct imei 
FROM eventdata 
where timestamp between TO_DATE("2016-06-01") AND TO_DATE("2016-07-17") 
AND event = "Use" AND clientversion like '3.2%') b 
on a.imei=b.imei 

Danke

Antwort

2

Alles hängt von Ihren Daten ab. Wenn Ihre Datasets zu viele Zeilen mit demselben imei enthalten, dann ist das Anwenden von distinct vor dem Join besser als das Anwenden von count (distinct) nach dem Join (Sie haben es in diesem Fall richtig geschrieben). Und umgekehrt: Wenn es ein paar wiederholte Reihen mit dem gleichen Imei gibt, dann können Sie sie zuerst verbinden. Das Anwenden von distinct auf jeden Datensatz vor dem Verbinden ist sicherer, je nach Daten langsamer. Ich würde empfehlen, Ihre Datensätze durch to_date (timestamp) -Feld (JJJJ-MM-TT) zu partitionieren, um die Partitionsbereinigung gemäß Ihrer WHERE-Klausel zu arbeiten (überprüfen Sie, ob es funktioniert). Partition auch nach Ereignisfeld, wenn Datensätze zu groß sind und viele Daten enthalten, wo Ereignis <> 'Verwenden'.

Es ist wichtig zu wissen, auf welcher Stufe es versagt. Studieren Sie die Ausnahme auch. Wenn es auf Mappern fehlschlägt, sollten Sie Ihre Unterabfragen optimieren (fügen Sie Partitionen wie erwähnt hinzu). Wenn es auf Reducer (Join) fehlschlägt, dann sollten Sie irgendwie Join verbessern (versuchen, Bytes pro Reducer - set hive.exec.reducers.bytes.per.reducer=67108864; oder noch weniger) zu reduzieren, wenn es auf Schreiber fehlschlägt (OrcWriter dann versuchen, Partition von SubText von Imei-Tabelle hinzuzufügen und durch substr(imei...) zu verteilen) am Ende der Abfrage, um den Druck auf Reduzierstücke zu reduzieren)

+0

Vielen Dank, das war sehr hilfreich. Ich konnte die gleiche Abfrage zu einem späteren Zeitpunkt ohne Probleme ausführen? Wäre das dann möglicherweise nur darauf zurückzuführen, dass andere Leute viele Anfragen auf dem Server ausführen? –

+0

Hmm ... 'GC overhead limit exceeded' bedeutet, dass Ihre Anwendung 98% versucht, den Speicher freizugeben und stattdessen einige nützliche Arbeit zu leisten. Vielleicht liegt es daran, dass es keinen freien Speicher mehr zu reservieren gibt, da der gesamte Speicher bereits von anderen Prozessen genutzt wird. Jedenfalls ist das ein Grund, sich darüber Gedanken zu machen. Außerdem können Sie versuchen, Ihrer Anwendung mehr Speicher zuzuweisen. Sehen Sie dies: https://blogs.msdn.microsoft.com/shanyu/2014/07/31/hadoop-yarn-memory-settings-in-hdinsight/ Tun Sie es, wenn es nichts zu optimieren gibt. – leftjoin

3

Um die Leistung zu verbessern, indem sie bei Ihrer Anfrage suchen: Ich würde die hive Tabellen von yyyy, mm, dd oder durch ersten beiden Ziffern der imei partitionieren, müssen Sie die Variable nach entscheiden müssen zu Ihrer Notwendigkeit, diese Tabellen und Datenmenge abzufragen. aber ich würde für yyyy, mm, dd stimmen, das wird Ihnen enorme Verbesserung der Leistung geben. siehe improving-query-performance-using-partitioning

Aber jetzt, diese sollten Sie einige Verbesserungen geben:

Select count(distinct(pd.imei)) 
from pingdata pd join eventdata ed on pd.imei=ed.imei 
where 
TO_DATE(pd.timestamp) between '2016-06-01' AND '2016-07-17' 
and pd.timestamp=ed.pd.timestamp 
and SUBSTR(pd.imei,12,2) in ('04','05') 
and ed.event = 'Use' AND ed.clientversion like '3.2%'; 

wenn TO_DATE(timestamp) Werte eingefügt werden am selben Tag, mit anderen Worten, wenn beide Werte für Datum gleich sind als and pd.timestamp=ed.pd.timestamp Bedingung ausgeschlossen werden sollte.

Select count(distinct(pd.imei)) 
from pingdata pd join eventdata ed on pd.imei=ed.imei 
where 
TO_DATE(pd.timestamp) between '2016-06-01' AND '2016-07-17' 
and SUBSTR(pd.imei,12,2) in ('04','05') 
and ed.event = 'Use' AND ed.clientversion like '3.2%'; 

Versuchen Sie, beide Abfragen auszuführen und die Ergebnisse zu vergleichen. Lassen Sie uns die Unterschiede wissen und wenn Sie das hilfreich finden.