2 votes

(SPARK) Quelle est la meilleure façon de partitionner des données sur lesquelles plusieurs filtres sont appliqués ?

Je travaille dans Spark (sur azure databricks) avec un fichier de 15 milliards de lignes qui ressemble à ceci :

+---------+---------------+----------------+-------------+--------+------+
|client_id|transaction_key|transaction_date|   product_id|store_id|spend|
+---------+---------------+----------------+-------------+--------+------+
|        1|  7587_20121224|      2012-12-24|     38081275|     787| 4.54|
|        1| 10153_20121224|      2012-12-24|         4011|    1053| 2.97|
|        2|  6823_20121224|      2012-12-24|    561122924|     683| 2.94|
|        3| 11131_20121224|      2012-12-24|     80026282|    1131|  0.4|
|        3|  7587_20121224|      2012-12-24|        92532|     787| 5.49|

Ces données sont utilisées pour toutes mes requêtes, qui consistent principalement en groupby (product_id par exemple), sum et count distinct :

results = trx.filter(col("transaction_date") > "2018-01-01"
                     & 
                     col("product_id").isin(["38081275", "4011"])
             .groupby("product_id")
             .agg(sum("spend").alias("total_spend"),
                  countdistinct("transaction_key").alias("number_trx"))

Je n'ai jamais besoin d'utiliser 100% de ces données, je commence toujours par un filtre sur :

  • date de la transaction (1 000 valeurs distinctes)
  • produit_id (1 000 000 de valeurs distinctes)
  • numéro de magasin (1 000 valeurs distinctes)

\==> Quelle est la meilleure façon de partitionner ces données dans un fichier parquet ?

J'ai initialement partitionné les données sur date de la transaction :

trx.write.format("parquet").mode("overwrite").partitionBy("transaction_date").save("dbfs:/linkToParquetFile")

Cela permettra de créer des partitions qui ont approximativement la même taille. Cependant, la plupart des requêtes nécessiteront de conserver au moins 60% de la taille de la partition. date de la transaction alors que seuls quelques produit_id sont généralement sélectionnés en une seule requête. (70% des numéro de magasin conservés en général)

\==> Existe-t-il un moyen de construire un fichier parquet en tenant compte de ce facteur ?

Il semble que le partitionnement des données sur produit_id créerait beaucoup trop de partitions...

Merci !

1voto

Kamrus Points 290

Par exemple, vous pouvez utiliser plusieurs colonnes pour le partitionnement (cela crée des sous-dossiers) et vous pouvez utiliser des filtres de partition.

une autre bonne idée est de regrouper plus d'informations aquí (pour éviter un brassage supplémentaire)

Exemple avec la ruche

trx.write.partitionBy("transaction_date", "store_id").bucketBy(1000, "product_id").saveAsTable("tableName")

pour le lire, utilisez

spark.table("tableName")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X