Je veux savoir si Spark connaît la clé de partitionnement du fichier parquet et utilise ces informations pour éviter les brassages.
Contexte:
Exécution Spark 2.0.1 exécutant SparkSession local. J'ai un jeu de données csv que j'enregistre en tant que fichier parquet sur mon disque comme ceci:
val df0 = spark
.read
.format("csv")
.option("header", true)
.option("delimiter", ";")
.option("inferSchema", false)
.load("SomeFile.csv"))
val df = df0.repartition(partitionExprs = col("numerocarte"), numPartitions = 42)
df.write
.mode(SaveMode.Overwrite)
.format("parquet")
.option("inferSchema", false)
.save("SomeFile.parquet")
Je crée 42 partitions par colonne numerocarte
. Cela devrait regrouper plusieurs numerocarte
dans la même partition. Je ne veux pas faire partitionBy ("numerocarte") au moment write
parce que je ne veux pas une partition par carte. Ce serait des millions d'entre eux.
Après cela, dans un autre script, j'ai lu ce SomeFile.parquet
fichier parquet et faire quelques opérations dessus. En particulier, je gère un window function
sur celui-ci où le partitionnement se fait sur la même colonne que le fichier parquet a été repartitionné.
import org.Apache.spark.sql.expressions.Window
import org.Apache.spark.sql.functions._
val df2 = spark.read
.format("parquet")
.option("header", true)
.option("inferSchema", false)
.load("SomeFile.parquet")
val w = Window.partitionBy(col("numerocarte"))
.orderBy(col("SomeColumn"))
df2.withColumn("NewColumnName",
sum(col("dollars").over(w))
Après read
je peux voir que le repartition
a fonctionné comme prévu et DataFrame df2
a 42 partitions et dans chacune d'elles se trouvent des cartes différentes.
Questions:
df2
est partitionné par la colonne numerocarte
?DataFrame
? Existe-t-il une commande pour cela? Je sais comment vérifier le nombre de partitions mais comment voir la clé de partitionnement?read
et 200 partitions après withColumn
ce qui suggère que Spark repartitionné mon DataFrame
.Spark sait-il que la trame de données df2 est partitionnée par une colonne de chiffres?
Ce ne est pas.
S'il ne sait pas, comment puis-je dire Spark les données sont déjà partitionnées par la colonne de droite?
Non. Ce n'est pas parce que vous enregistrez des données qui ont été mélangées qu'elles seront chargées avec les mêmes divisions.
Comment puis-je vérifier une clé de partitionnement de DataFrame?
Il n'y a pas de clé de partitionnement une fois que vous avez chargé les données, mais vous pouvez vérifier queryExecution
pour Partitioner
.
En pratique:
partitionBy
de DataFrameWriter
.bucketBy
avec les métastores et les tables persistantes.Voir Comment définir le partitionnement de DataFrame? pour des exemples détaillés.
Je réponds à ma propre question pour référence future ce qui a fonctionné.
Suite à la suggestion de @ user8371915, bucketBy fonctionne!
J'enregistre mon DataFrame df
:
df.write
.bucketBy(250, "userid")
.saveAsTable("myNewTable")
Puis quand j'ai besoin de charger ce tableau:
val df2 = spark.sql("SELECT * FROM myNewTable")
val w = Window.partitionBy("userid")
val df3 = df2.withColumn("newColumnName", sum(col("someColumn")).over(w)
df3.explain
Je confirme que lorsque je fais des fonctions de fenêtre sur df2
Partitionné par userid
il n'y a pas de mélange! Merci @ user8371915!
Certaines choses que j'ai apprises en enquêtant
spark.read.format("parquet").load("path/to/myNewTable")
mais le DataFrame
créé de cette façon ne conservera pas le partitionnement d'origine! Vous devez utiliser spark.sql
select
pour obtenir une partition correctement DataFrame
.spark.sql("describe formatted myNewTable").collect.foreach(println)
. Cela vous indiquera quelles colonnes ont été utilisées pour le regroupement et le nombre de regroupements..sortBy()
et le tri sera également conservé dans la table Hive. df.write.bucketBy(250, "userid").sortBy("somColumnName").saveAsTable("myNewTable")
myNewTable
est enregistrée dans un dossier spark-warehouse
Dans mon projet local Scala SBT. Lors de l'enregistrement en mode cluster avec mesos via spark-submit
, Il est enregistré dans l'entrepôt Hive. Pour moi, il était situé dans /user/Hive/warehouse
.spark-submit
, Vous devez ajouter à votre SparkSession
deux options: .config("Hive.metastore.uris", "thrift://addres-to-your-master:9083")
et .enableHiveSupport()
. Sinon, les tables Hive que vous avez créées ne seront pas visibles.spark.sql("USE your database")
avant le regroupement.Mise à jour 05-02-2018
J'ai rencontré des problèmes avec spark bucketing et création de tables Hive. Veuillez vous référer aux questions, réponses et commentaires dans Pourquoi est Spark saveAsTable avec bucketBy) créer des milliers de fichiers?