Je dois charger des données à partir d'une table Hive en utilisant Spark SQL HiveContext
et charger dans HDFS. Par défaut, le DataFrame
de la sortie SQL a 2 partitions. Pour obtenir plus de parallélisme, j'ai besoin de plus de partitions hors du SQL. Il n'y a pas de méthode surchargée dans HiveContex
t pour prendre le nombre de paramètres de partitions.
Le repartitionnement du RDD entraîne un brassage et entraîne un temps de traitement plus long.
>
val result = sqlContext.sql("select * from bt_st_ent")
A la sortie du journal de:
Starting task 0.0 in stage 131.0 (TID 297, aster1.com, partition 0,NODE_LOCAL, 2203 bytes)
Starting task 1.0 in stage 131.0 (TID 298, aster1.com, partition 1,NODE_LOCAL, 2204 bytes)
Je voudrais savoir s'il existe un moyen d'augmenter la taille des partitions de la sortie SQL.
Spark <2.0 :
Vous pouvez utiliser les options de configuration Hadoop:
mapred.min.split.size
.mapred.max.split.size
ainsi que la taille du bloc HDFS pour contrôler la taille de la partition pour les formats basés sur le système de fichiers *.
val minSplit: Int = ???
val maxSplit: Int = ???
sc.hadoopConfiguration.setInt("mapred.min.split.size", minSplit)
sc.hadoopConfiguration.setInt("mapred.max.split.size", maxSplit)
Spark 2.0 + :
Vous pouvez utiliser spark.sql.files.maxPartitionBytes
configuration:
spark.conf.set("spark.sql.files.maxPartitionBytes", maxSplit)
Dans les deux cas, ces valeurs peuvent ne pas être utilisées par une API de source de données spécifique, vous devez donc toujours vérifier les détails de la documentation/implémentation du format que vous utilisez.
* D'autres formats d'entrée peuvent utiliser des paramètres différents. Voir par exemple
De plus, Datasets
créé à partir de RDDs
héritera de la disposition des partitions de leurs parents.
De même, les tables regroupées utiliseront la disposition de compartiment définie dans le métastore avec une relation 1: 1 entre le compartiment et la partition Dataset
.
Un problème très courant et douloureux. Vous devez rechercher une clé qui distribue les données dans des partitions uniformes. Vous pouvez utiliser le DISTRIBUTE BY
et CLUSTER BY
opérateurs pour indiquer spark pour regrouper les lignes dans une partition. Cela entraînera des frais généraux sur la requête elle-même. Mais il en résultera des partitions de taille égale. Deepsense a un très bon tutoriel à ce sujet.
Si votre SQL effectue un shuffle (par exemple, il a une jointure ou une sorte de groupe par), vous pouvez définir le nombre de partitions en définissant la propriété 'spark.sql.shuffle.partitions'
sqlContext.setConf( "spark.sql.shuffle.partitions", 64)
Pour donner suite à ce que suggère Fokko, vous pouvez utiliser une variable aléatoire pour regrouper.
val result = sqlContext.sql("""
select * from (
select *,random(64) as Rand_part from bt_st_ent
) cluster by Rand_part""")