将大型镶木地板文件(5亿行/ 1000列)写入S3需要花费太多时间

时间:2017-05-29 13:41:02

标签: performance apache-spark amazon-s3 parquet

首先让我介绍一下我的用例,我每天会收到5亿行,如下:

ID |分类

1 | cat1,cat2,cat3,...,catn

2 | cat1,catx,caty,...,anothercategory

输入数据:50个压缩的csv文件,每个文件为250 MB - >总计:12.5 GB压缩

目的是回答以下问题:查找属于Catx和Caty的所有ID,找到属于cat3而不是caty等的ID ...:ie: cat1 U cat2 中的ID ids cat3∩catx

假设动态创建类别(每天我有一组新的类别),我的企业想要探索所有可能的交叉点和联合(我们没有一套固定的查询)我想出了以下解决方案:

我写了一个火花作业,将日期转换为脂肪稀疏矩阵,其中列是所有可能的类别加上列ID,对于每一行和列,我设置为true,如果id属于此类别,则为false,否则为false:

ID | cat1 | cat2 | cat3 | ... | catn | catx | caty | anothercategory | ....

1 |是的|是的|真| ... |是的| false | false | false | ....

2 | true | false | false | ... | false |是的|是的| true | ....

SQL可以简单地回答我的问题,例如,如果我想找到属于类别cat1和类别catx的所有id,那么我对该矩阵运行以下sql查询:

从MyTable中选择id,其中cat1 = true且catx = true;

我选择将这个稀疏矩阵保存为压缩的镶木地板文件,我对稀疏性和查询性质做出了这个选择,我相信柱状存储是最合适的存储格式。

现在我在这里描述的用例是我的观察,我可能会遗漏一些优化点:

  • 转换后的12.5GB压缩输入数据需要~300GB写这个稀疏矩阵作为镶木地板需要太多的时间和资源,花了2,3小时用spark1.6独立集群的6个aws实例r4.4xlarge(我设置的足够并行化以分配工作并利用我所拥有的所有工人。
  • 我最终得到了太多镶木地板文件,我对最小的镶木地板文件的并行化程度越高。好像每个RDD给出一个镶木地板文件 - >因为我的查询遍历所有列值

  • ,所以扫描不是太多小文件
  • 我经历了很多帖子,但仍然不明白为什么写入500万/ 1000柱压缩拼花到S3要花费这么多时间,一旦在S3上小文件总和达到~35G

  • 查看应用程序主UI,作业在写作阶段,转换阶段和洗牌时挂起似乎是资源/时间消耗。

  • 我试图调整镶木地板参数,例如group_size,page_size和disable_dictionnary,但没有看到性能改进。

  • 我尝试分区到更大的RDD并将它们写入S3以获得更大的镶木地板文件,但这项工作耗费了太多时间,最后我将其杀了。

  • 我可以在~1小时内使用一个类型为r4.16xlarge的4个aws实例的spark 2.1独立集群来运行这个工作,我觉得我正在使用一个巨大的集群来实现一个小的改进,唯一的好处我得到的是运行更多并行任务。我错过了什么吗?我可以利用~1 To RAM来更好地实现这一目标并获得更大的镶木地板文件。

你对使用spark在S3上写大型镶木地板文件有什么反馈吗?

我也想知道你对这个解决方案的看法/批评。

谢谢和问候。

1 个答案:

答案 0 :(得分:2)

这是Spark重读东西的组合,用于做摘要(你可以禁用的东西)和用于提交重命名()的工作的算法,它在S3中被副本模仿。

有关详细信息,请参阅“Apache Spark and object stores”和一些可以略微加快工作速度的开关(禁用摘要,使用较少重命名的算法)

即使有了这些,你也会得到延迟,因为S3最终是一致的,有可能产生腐败的输出。最安全的是写入瞬态HDFS文件系统,然后在所有工作结束时复制到S3