Je comprends la théorie de base de la partition de génération textFile
pour chaque fichier, tandis que wholeTextFiles
génère un RDD de valeurs de paires, où la clé est le chemin de chaque fichier, la valeur correspond au contenu de chaque fichier.
Maintenant, d’un point de vue technique, quelle est la différence entre:
val textFile = sc.textFile("my/path/*.csv", 8)
textFile.getNumPartitions
et
val textFile = sc.wholeTextFiles("my/path/*.csv",8)
textFile.getNumPartitions
Dans les deux méthodes, je génère 8 partitions. Alors, pourquoi devrais-je utiliser wholeTextFiles
en premier lieu, et quel est son bénéfice par rapport à textFile
?
Comme vous l'avez dit, la principale différence est que textFile
renverra un RDD avec chaque ligne en tant qu'élément, tandis que wholeTextFiles
renverra un PairRDD avec la clé correspondant au chemin du fichier. S'il n'est pas nécessaire de séparer les données en fonction du fichier, utilisez simplement textFile
.
Lors de la lecture de fichiers non compressés avec textFile
, les données seront divisées en tronçons de 32 Mo. Ceci est avantageux du point de vue de la mémoire. Cela signifie également que l'ordre des lignes est perdu. Si l'ordre doit être conservé, alors wholeTextFiles
doit être utilisé.
wholeTextFiles
lit l'intégralité du contenu d'un fichier à la fois, il ne sera ni partiellement déversé sur le disque ni partiellement nettoyé. Chaque fichier sera traité par un noyau et les données pour chaque fichier seront une seule machine, ce qui rendra plus difficile la répartition de la charge.
textFile
générer une partition pour chaque fichier, alors quewholeTextFiles
génère un RDD de valeurs de paires
Ce n'est pas exact:
textFile
charge un ou plusieurs fichiers, avec chaque line en tant que record dans le RDD résultant. Un fichier unique peut être divisé en plusieurs partitions s'il est suffisamment volumineux (dépend du nombre de partitions demandées, du nombre de partitions par défaut de Spark et du système de fichiers sous-jacent). Lors du chargement de plusieurs fichiers à la fois, cette opération "perd" la relation entre un enregistrement et le fichier qui le contient - c’est-à-dire qu’il n’ya aucun moyen de savoir quel fichier contient quelle ligne. L'ordre des enregistrements dans le RDD suivra l'ordre alphabétique des fichiers et l'ordre des enregistrements dans les fichiers (l'ordre n'est pas "perdu").
wholeTextFiles
préserve la relation entre les données et les fichiers qui les contiennent en chargeant les données dans une PairRDD
avec un enregistrement par fichier d'entrée . L'enregistrement aura la forme (fileName, fileContent)
. Cela signifie que charger des fichiers volumineux est risqué (peut entraîner de mauvaises performances ou OutOfMemoryError
car chaque fichier sera nécessairement stocké sur un seul nœud). Le partitionnement est effectué en fonction de la saisie de l'utilisateur ou de la configuration de Spark, avec plusieurs fichiers potentiellement chargés dans une seule partition.
De manière générale, textFile
sert au cas d'utilisation courant consistant à simplement charger un grand nombre de données (quelle que soit la manière dont elles sont décomposées en fichiers). readWholeFiles
ne devrait être utilisé que si vous avez réellement besoin de connaître le nom du fichier d'origine de chaque enregistrement, et si vous savez que tous les fichiers sont suffisamment petits.
A partir de Spark2.1.1, voici le code pour textFile.
def textFile(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {
assertNotStopped()
hadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text],
minPartitions).map(pair => pair._2.toString).setName(path) }
Qui utilise en interne hadoopFile pour lire les fichiers locaux, les fichiers HDFS et S3 en utilisant un modèle tel que file://
, hdfs://
et s3a://
Où comme WholeTextFile la syntaxe est comme ci-dessous
def wholeTextFiles(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[(String, String)] = withScope
Si nous observons que la syntaxe des deux méthodes est la même, mais textfile est utile pour lire les fichiers, où wholeTextFiles est utilisé pour lire les répertoires des petits fichiers. Cependant, nous pouvons également utiliser des fichiers plus volumineux, mais les performances peuvent en pâtir.
Ainsi, lorsque vous voulez traiter des fichiers volumineux, textFile est la meilleure option, alors que si nous voulons traiter avec le répertoire des fichiers plus petits, wholeTextFile est préférable.
textfile () lit un fichier texte et retourne un RDD de chaînes. Par exemple, sc.textFile ("/ mydata.txt") créera un RDD dans lequel chaque ligne individuelle est un élément.
wholeTextFile () lit un répertoire de fichiers texte et renvoie pairRDD . Par exemple, s'il y a peu de fichiers dans un répertoire, la méthode wholeTextFile () créera une paire RDD avec le nom de fichier et le chemin d'accès, et la valeur étant le fichier entier. en tant que chaîne.