(SPARK) Как лучше всего разделить данные, к которым применяется несколько фильтров?

Я работаю в Spark (на лазурных блоках данных) с файлом из 15 миллиардов строк, который выглядит следующим образом:

+---------+---------------+----------------+-------------+--------+------+
|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|

Эти данные используются для всех моих запросов, которые в основном состоят из групп (например, product_id), суммирования и подсчета различных:

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"))

Мне никогда не нужно использовать 100% этих данных, я всегда начинаю с фильтра:

  • transaction_date (1000 различных значений)
  • product_id (1 000 000 различных значений)
  • store_id (1000 различных значений)

==> Как лучше всего разделить эти данные в паркетном файле?

Сначала я разделил данные на transaction_date :

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

Это создаст разделы примерно одинакового размера. Однако для большинства запросов требуется сохранить не менее 60 % transaction_date, тогда как в одном запросе обычно выбираются лишь несколько product_id. (обычно сохраняется 70% store_id)

==> Есть ли способ построить файл паркета с учетом этого?

Кажется, что разделение данных по product_id создаст слишком много разделов...

Спасибо!


person RobL    schedule 08.04.2019    source источник


Ответы (1)


например, вы можете использовать несколько столбцов для разделения (он создает подпапки), а spark может использовать фильтры разделов.

Еще одна хорошая идея — собрать дополнительную информацию здесь (чтобы избегайте лишней перетасовки)

Пример с ульем

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

чтобы прочитать это использовать

spark.table("tableName")
person Kamrus    schedule 08.04.2019
comment
Спасибо @Kamrus, это помогло! Я почему-то думал, что разбиение по нескольким столбцам создаст папки на основе комбинации этих столбцов. Однако он создает подпапки в каждой папке, что позволяет мне очень эффективно использовать фильтры разделов. - person RobL; 15.04.2019