web-dev-qa-db-fra.com

Comprendre spark plan physique

J'essaie de comprendre les plans physiques sur spark mais je ne comprends pas certaines parties car elles semblent différentes des rdbms traditionnels. Par exemple, dans ce plan ci-dessous, c'est un plan sur une requête sur une table Hive. La requête est la suivante:

select
        l_returnflag,
        l_linestatus,
        sum(l_quantity) as sum_qty,
        sum(l_extendedprice) as sum_base_price,
        sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
        sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
        avg(l_quantity) as avg_qty,
        avg(l_extendedprice) as avg_price,
        avg(l_discount) as avg_disc,
        count(*) as count_order
    from
        lineitem
    where
        l_shipdate <= '1998-09-16'
    group by
        l_returnflag,
        l_linestatus
    order by
        l_returnflag,
        l_linestatus;


== Physical Plan ==
Sort [l_returnflag#35 ASC,l_linestatus#36 ASC], true, 0
+- ConvertToUnsafe
   +- Exchange rangepartitioning(l_returnflag#35 ASC,l_linestatus#36 ASC,200), None
      +- ConvertToSafe
         +- TungstenAggregate(key=[l_returnflag#35,l_linestatus#36], functions=[(sum(l_quantity#31),mode=Final,isDistinct=false),(sum(l_extendedpr#32),mode=Final,isDistinct=false),(sum((l_extendedprice#32 * (1.0 - l_discount#33))),mode=Final,isDistinct=false),(sum(((l_extendedprice#32 * (1.0l_discount#33)) * (1.0 + l_tax#34))),mode=Final,isDistinct=false),(avg(l_quantity#31),mode=Final,isDistinct=false),(avg(l_extendedprice#32),mode=Fl,isDistinct=false),(avg(l_discount#33),mode=Final,isDistinct=false),(count(1),mode=Final,isDistinct=false)], output=[l_returnflag#35,l_linestatus,sum_qty#0,sum_base_price#1,sum_disc_price#2,sum_charge#3,avg_qty#4,avg_price#5,avg_disc#6,count_order#7L])
            +- TungstenExchange hashpartitioning(l_returnflag#35,l_linestatus#36,200), None
               +- TungstenAggregate(key=[l_returnflag#35,l_linestatus#36], functions=[(sum(l_quantity#31),mode=Partial,isDistinct=false),(sum(l_exdedprice#32),mode=Partial,isDistinct=false),(sum((l_extendedprice#32 * (1.0 - l_discount#33))),mode=Partial,isDistinct=false),(sum(((l_extendedpri32 * (1.0 - l_discount#33)) * (1.0 + l_tax#34))),mode=Partial,isDistinct=false),(avg(l_quantity#31),mode=Partial,isDistinct=false),(avg(l_extendedce#32),mode=Partial,isDistinct=false),(avg(l_discount#33),mode=Partial,isDistinct=false),(count(1),mode=Partial,isDistinct=false)], output=[l_retulag#35,l_linestatus#36,sum#64,sum#65,sum#66,sum#67,sum#68,count#69L,sum#70,count#71L,sum#72,count#73L,count#74L])
                  +- Project [l_discount#33,l_linestatus#36,l_tax#34,l_quantity#31,l_extendedprice#32,l_returnflag#35]
                     +- Filter (l_shipdate#37 <= 1998-09-16)
                        +- HiveTableScan [l_discount#33,l_linestatus#36,l_tax#34,l_quantity#31,l_extendedprice#32,l_shipdate#37,l_returnflag#35], astoreRelation default, lineitem, None

Pour ce que je comprends dans le plan, c'est:

  1. Commence d'abord par une analyse de la table Hive

  2. Ensuite, il filtre en utilisant où la condition

  3. Projetez ensuite pour obtenir les colonnes que nous voulons

  4. Alors TungstenAggregate?

  5. Alors TungstenExchange?

  6. Puis TungstenAggregate à nouveau?

  7. Alors ConvertToSafe?

  8. Trie ensuite le résultat final

Mais je ne comprends pas les étapes 4, 5, 6 et 7. Tu sais ce que c'est? Je cherche des informations à ce sujet pour comprendre le plan mais je ne trouve rien de concret.

21
codin

Regardons la structure de la requête SQL que vous utilisez:

SELECT
    ...  -- not aggregated columns  #1
    ...  -- aggregated columns      #2
FROM
    ...                          -- #3
WHERE
    ...                          -- #4
GROUP BY
    ...                          -- #5
ORDER BY
    ...                          -- #6

Comme vous le soupçonnez déjà:

  • Filter (...) correspond aux prédicats de la clause WHERE (#4)
  • Project ... Limite le nombre de colonnes à celles requises par une union de (#1 Et #2, Et #4/#6 S'il n'est pas présent dans SELECT)
  • HiveTableScan correspond à la clause FROM (#3)

Les pièces restantes peuvent être attribuées comme suit:

  • #2 De la clause SELECT - functions champ dans TungstenAggregates
  • Clause GROUP BY (#5):

    • TungstenExchange/partitionnement par hachage
    • key champ dans TungstenAggregates
  • #6 - Clause ORDER BY.

Le projet Tungsten décrit en général un ensemble d'optimisations utilisées par Spark DataFrames (-sets), notamment:

  • gestion explicite de la mémoire avec Sun.misc.Unsafe. Cela signifie une utilisation de la mémoire "native" (hors segment) et une allocation/libération explicite de mémoire en dehors de la gestion du GC. Ces conversions correspondent aux étapes ConvertToUnsafe/ConvertToSafe du plan d'exécution. Vous pouvez en apprendre plus sur les détails dangereux à propos de nderstanding Sun.misc.Unsafe
  • génération de code - différentes astuces de méta-programmation conçues pour générer du code mieux optimisé lors de la compilation. Vous pouvez le considérer comme un compilateur interne Spark qui fait des choses comme réécrire du code fonctionnel de Nice en laid pour les boucles).

Pour en savoir plus sur Tungsten en général, consultez Project Tungsten: Bringing Apache Spark Closer to Bare Metal . Apache Spark = 2.0: plus rapide, plus facile et plus intelligent fournit quelques exemples de génération de code.

TungstenAggregate se produit deux fois car les données sont d'abord agrégées localement sur chaque partition, puis mélangées, puis finalement fusionnées. Si vous connaissez l'API RDD, ce processus est à peu près équivalent à reduceByKey.

Si le plan d'exécution n'est pas clair, vous pouvez également essayer de convertir le DataFrame résultant en RDD et d'analyser la sortie de toDebugString.

26
zero323

Tungsten est le nouveau moteur de mémoire de Spark depuis la version 1.4, qui gère les données en dehors de la JVM pour économiser une surcharge du GC. Vous pouvez imaginer que cela implique de copier des données depuis et vers la JVM. C'est tout. Dans Spark 1.5, vous pouvez désactiver Tungsten via spark.sql.tungsten.enabled, Puis vous verrez "l'ancien" plan, dans Spark 1.6 Je pense que vous ne pouvez plus le désactiver.

3
piggybox