Skapa funktioner för data i ett Hadoop-kluster med Hive-frågor

Det här dokumentet visar hur du skapar funktioner för data som lagras i Azure HDInsight Hadoop kluster med Hive-frågor. Dessa Hive-frågor använder inbäddad Hive User-Defined Functions (UDF), skripten som tillhandahålls.

De åtgärder som krävs för att skapa funktioner kan vara minnesintensiva. Prestanda för Hive-frågor blir mer kritiska i sådana fall och kan förbättras genom justering av vissa parametrar. Justeringen av dessa parametrar beskrivs i det sista avsnittet.

Exempel på de frågor som visas är specifika för scenarier med taxiresor i New York finns också på GitHub-lagringsplatsen. Dessa frågor har redan dataschemat angivet och är redo att skickas för körning. I det sista avsnittet diskuteras även parametrar som användare kan justera så att prestanda för Hive-frågor kan förbättras.

Den här uppgiften är ett steg i TDSP (Team Data Science Process).

Förutsättningar

Den här artikeln förutsätter att du har:

Funktionsgenerering

I det här avsnittet beskrivs flera exempel på hur funktioner kan genereras med Hive-frågor. När du har genererat ytterligare funktioner kan du antingen lägga till dem som kolumner i den befintliga tabellen eller skapa en ny tabell med ytterligare funktioner och primärnyckel, som sedan kan sammanfogas med den ursprungliga tabellen. Här är de exempel som visas:

  1. Frekvensbaserad funktionsgenerering
  2. Risker med kategoriska variabler i binär klassificering
  3. Extrahera funktioner från Datetime Field
  4. Extrahera funktioner från textfält
  5. Beräkna avståndet mellan GPS-koordinater

Frekvensbaserad funktionsgenerering

Det är ofta användbart att beräkna frekvenserna för nivåerna för en kategorisk variabel eller frekvenserna för vissa kombinationer av nivåer från flera kategoriska variabler. Användare kan använda följande skript för att beräkna dessa frekvenser:

select
    a.<column_name1>, a.<column_name2>, a.sub_count/sum(a.sub_count) over () as frequency
from
(
    select
        <column_name1>,<column_name2>, count(*) as sub_count
    from <databasename>.<tablename> group by <column_name1>, <column_name2>
)a
order by frequency desc;

Risker med kategoriska variabler i binär klassificering

Vid binär klassificering måste icke-numeriska kategoriska variabler konverteras till numeriska funktioner när de modeller som används endast använder numeriska funktioner. Den här konverteringen görs genom att ersätta varje icke-numerisk nivå med en numerisk risk. Det här avsnittet visar några allmänna Hive-frågor som beräknar riskvärden (loggoder) för en kategorisk variabel.

set smooth_param1=1;
set smooth_param2=20;
select
    <column_name1>,<column_name2>,
    ln((sum_target+${hiveconf:smooth_param1})/(record_count-sum_target+${hiveconf:smooth_param2}-${hiveconf:smooth_param1})) as risk
from
    (
    select
        <column_nam1>, <column_name2>, sum(binary_target) as sum_target, sum(1) as record_count
    from
        (
        select
            <column_name1>, <column_name2>, if(target_column>0,1,0) as binary_target
        from <databasename>.<tablename>
        )a
    group by <column_name1>, <column_name2>
    )b

I det här exemplet är variabler smooth_param1 och inställda för att jämna ut de smooth_param2 riskvärden som beräknas från data. Riskerna har ett intervall mellan -Inf och Inf. En risk > 0 anger att sannolikheten för att målet är lika med 1 är större än 0,5.

När risktabellen har beräknats kan användare tilldela riskvärden till en tabell genom att koppla den till risktabellen. Hive-anslutningsfrågan angavs i föregående avsnitt.

Extrahera funktioner från datetime-fält

Hive levereras med en uppsättningudf:er för bearbetning av datetime-fält. I Hive är standardformatet datetime "yyyy-MM-dd 00:00:00" (till exempel "1970-01-01 12:21:32"). Det här avsnittet visar exempel som extraherar dagen i en månad, månaden från ett datetime-fält och andra exempel som konverterar en datetime-sträng i ett annat format än standardformatet till en datetime-sträng i standardformat.

select day(<datetime field>), month(<datetime field>)
from <databasename>.<tablename>;

Den här Hive-frågan förutsätter <datetime field> att är i standardformatet datetime.

Om ett datetime-fält inte har standardformatet måste du först konvertera fältet datetime till Unix-tidsstämpel och sedan konvertera Unix-tidsstämpeln till en datetime-sträng som har standardformatet. När datetime är i standardformat kan användarna använda inbäddade datetime-användarprogram för att extrahera funktioner.

select from_unixtime(unix_timestamp(<datetime field>,'<pattern of the datetime field>'))
from <databasename>.<tablename>;

I den här frågan, om har mönstret <datetime field> 03/26/2015 12:04:39, <pattern of the datetime field> ska vara 'MM/dd/yyyy HH:mm:ss' . För att testa den kan användarna köra

select from_unixtime(unix_timestamp('05/15/2015 09:32:10','MM/dd/yyyy HH:mm:ss'))
from hivesampletable limit 1;

Hivesampletable i den här frågan är förinstallerad på Azure HDInsight Hadoop kluster som standard när klustren etableras.

Extrahera funktioner från textfält

När Hive-tabellen har ett textfält som innehåller en sträng med ord som avgränsas med blanksteg, extraherar följande fråga längden på strängen och antalet ord i strängen.

select length(<text field>) as str_len, size(split(<text field>,' ')) as word_num
from <databasename>.<tablename>;

Beräkna avstånd mellan uppsättningar med GPS-koordinater

Frågan som anges i det här avsnittet kan tillämpas direkt på nyc-taxi-resedata. Syftet med den här frågan är att visa hur du använder en inbäddad matematisk funktion i Hive för att generera funktioner.

De fält som används i den här frågan är GPS-koordinaterna för upphämtnings- och avlämningsplatserna, med namnet pickup _ longitude, pickup _ latitude, dropoff _ longitude och dropoff _ latitud. Frågorna som beräknar det direkta avståndet mellan koordinaterna för upphämtning och avlämning är:

set R=3959;
set pi=radians(180);
select pickup_longitude, pickup_latitude, dropoff_longitude, dropoff_latitude,
    ${hiveconf:R}*2*2*atan((1-sqrt(1-pow(sin((dropoff_latitude-pickup_latitude)
    *${hiveconf:pi}/180/2),2)-cos(pickup_latitude*${hiveconf:pi}/180)
    *cos(dropoff_latitude*${hiveconf:pi}/180)*pow(sin((dropoff_longitude-pickup_longitude)*${hiveconf:pi}/180/2),2)))
    /sqrt(pow(sin((dropoff_latitude-pickup_latitude)*${hiveconf:pi}/180/2),2)
    +cos(pickup_latitude*${hiveconf:pi}/180)*cos(dropoff_latitude*${hiveconf:pi}/180)*
    pow(sin((dropoff_longitude-pickup_longitude)*${hiveconf:pi}/180/2),2))) as direct_distance
from nyctaxi.trip
where pickup_longitude between -90 and 0
and pickup_latitude between 30 and 90
and dropoff_longitude between -90 and 0
and dropoff_latitude between 30 and 90
limit 10;

Matematiska ekvationer som beräknar avståndet mellan två GPS-koordinater finns på webbplatsen För skript för flyttbar typ, som har skrivits av Peter Lapisu. I det här Javascript är toRad() funktionen bara lat_or_lon pi/180, som konverterar grader till radianer. Här är lat_or_lon latitud eller longitud. Eftersom Hive inte tillhandahåller funktionen , men tillhandahåller funktionen , implementeras funktionen av funktionen i Hive-frågan ovan med hjälp av definitionen atan2 atan som anges i atan2 atan Wikipedia.

Skapa arbetsyta

En fullständig lista över Hive-inbäddadeudf:er finns i avsnittet Inbyggda funktionerApache Hive wiki).

Avancerade ämnen: Finjustera Hive-parametrar för att förbättra frågehastigheten

Standardparameterinställningarna för Hive-klustret kanske inte är lämpliga för Hive-frågorna och de data som frågorna bearbetar. I det här avsnittet beskrivs några parametrar som användare kan justera för att förbättra prestanda för Hive-frågor. Användarna måste lägga till parameterjusteringsfrågor innan frågorna för bearbetning av data.

  1. Java-heaputrymme: För frågor som rör sammanfogning av stora datamängder eller bearbetning av långa poster är slut på heaputrymme ett av de vanligaste felen. Du kan undvika det här felet genom att ange parametrarna mapreduce.map.java.opts och mapreduce.task.io.sort.mb till önskade värden. Här är ett exempel:

    set mapreduce.map.java.opts=-Xmx4096m;
    set mapreduce.task.io.sort.mb=-Xmx1024m;
    

    Den här parametern allokerar 4 GB minne till Java-heaputrymmet och gör även sorteringen mer effektiv genom att allokera mer minne för den. Det är en bra idé att leka med dessa allokeringar om det finns jobbfel som rör heap-utrymme.

  2. DFS-blockstorlek: Den här parametern anger den minsta dataenhet som filsystemet lagrar. Om DFS-blockstorleken till exempel är 128 MB lagras alla data som är mindre än och upp till 128 MB i ett enda block. Data som är större än 128 MB tilldelas extra block.

  3. Om du väljer en liten blockstorlek leder det till stora omkostnader i Hadoop eftersom namnnoden måste bearbeta många fler begäranden för att hitta det relevanta blocket som hör till filen. En rekommenderad inställning när du hanterar gigabyte (eller större) data är:

    set dfs.block.size=128m;
    
  4. Optimera kopplingsåtgärden i Hive: Även om kopplingsåtgärder i map/reduce-ramverket vanligtvis sker i reduce-fasen kan du ibland uppnå enorma vinster genom att schemalägga kopplingar i map-fasen (kallas även "mapjoins"). Ange det här alternativet:

    set hive.auto.convert.join=true;
    
  5. Ange antalet mappare till Hive: Även om Hadoop tillåter användaren att ange antalet reducerare, anges vanligtvis inte antalet mappningar av användaren. Ett trick som tillåter viss kontroll över det här talet är att välja Hadoop-variablerna mapred.min.split.size och mapred.max.split.size när storleken på varje map-uppgift bestäms av:

    num_maps = max(mapred.min.split.size, min(mapred.max.split.size, dfs.block.size))
    

    Standardvärdet för:

    • mapred.min.split.size är 0, det vill säga

    • mapred.max.split.size är Long.MAX och för

    • dfs.block.size är 64 MB.

      Med tanke på datastorleken kan vi justera dessa parametrar genom att "ange" dem så att vi kan justera antalet mappningar som används.

  6. Här är några andra mer avancerade alternativ för att optimera Hive-prestanda. Med de här alternativen kan du ange det minne som allokeras till map- och reduce-uppgifter och kan vara användbara för att justera prestanda. Tänk på att mapreduce.reduce.memory.mb inte kan vara större än den fysiska minnesstorleken för varje arbetsnod i Hadoop-klustret.

    set mapreduce.map.memory.mb = 2048;
    set mapreduce.reduce.memory.mb=6144;
    set mapreduce.reduce.java.opts=-Xmx8192m;
    set mapred.reduce.tasks=128;
    set mapred.tasktracker.reduce.tasks.maximum=128;