使用Databricks将Google Api的结果写入数据湖

时间:2019-04-11 08:30:08

标签: python apache-spark azure-data-lake databricks google-api-python-client

我正在通过Databricks上的Python SDK从Google管理员报告用户使用情况Api中获取用户使用情况数据。每天的数据量大约为10万条记录,我通过一个批处理进行了一个晚上的记录。 api返回的最大页面大小为1000,因此我大致将其称为1000,以获取当天所需的数据。一切正常。

我的最终目标是将原始格式的数据存储在数据湖(Azure Gen2,但与该问题无关)中。稍后,我将使用Databricks将数据转换为汇总报告模型,并将PowerBI置于其之上,以跟踪一段时间内Google App的使用情况。

作为C#程序员,我是Python和Spark的新手:我当前的方法是从api请求第一千条记录的第一页,然后将其作为JSON文件直接写入datalake,然后获取下一页集和也写。文件夹结构类似于“ \ raw \ googleuser \ YYYY \ MM \ DD \ data1.json”。

我想在原始区域中将数据保持为最原始的形式,并且不进行过多的转换。第二个过程可以提取我需要的字段,用元数据标记它,并将其写回Parquet,以便按功能使用。这就是为什么我正在考虑将其编写为JSON的原因。

这意味着第二个过程需要将JSON读取到一个数据帧中,在这里我可以对其进行转换并将其编写为镶木地板(这部分也很简单)。

因为我使用的是Google Api,所以我不使用Json-它返回dict对象(具有复杂的嵌套)。我可以使用json.dump()将其提取为Json字符串,但无法弄清楚如何直接将STRING写入我的数据湖。一旦将其放入数据帧中,我就可以轻松地以任何格式编写它,但是将其从Json转换为数据帧然后从本质上返回到Json只是为了编写它似乎在性能上有开销。

这是我尝试过的事情和结果:

  1. 建立pyspark.sql.Rows的列表,并在所有分页的末尾(行数为100k)-使用spark.createDataFrame(rows)将其转换为数据框。一旦它是一个数据框,那么我可以将其另存为Json文件。这可行,但效率低下。
  2. 使用json.dump(request)在Json中获取1000条记录的字符串。我可以使用以下代码将其写入Databricks文件系统:

    with open("/dbfs/tmp/googleuserusagejsonoutput-{0}.json" .format(keyDateFilter), 'w') as f: f.write(json.dumps(response))

    但是,我必须使用以下命令将其移动到我的Azure数据湖:

    dbutils.fs.cp("/tmp/test_dbfs1.txt", datalake_path + dbfs_path + "xyz.json")

    然后,我得到接下来的1000条记录,并继续进行操作。我似乎无法在数据湖存储(Azure abfss驱动程序)中使用open()方法目录,否则这将是一个不错的解决方案。首先将其转储到本地然后移动它似乎很脆弱而且很奇怪。

  3. 与选项1相同,但是每隔1000条记录将数据帧转储到datalake并覆盖它(以便内存一次最多增加1000条记录)

  4. 忽略转储原始Json的规则。将数据整理成我想要的最简单的格式,并删除我不需要的所有多余数据。这将导致更小的占用空间,然后将采用上述选项1或3。 (这是第二个问题-以原始格式保存来自Api的所有数据的原则,以便随着需求的变化,我总是在数据湖中拥有历史数据,并且可以更改转换例程以从中提取不同的指标因此,我目前不愿意删除任何数据。

任何建议请感激...

1 个答案:

答案 0 :(得分:1)

将湖安装到您的数据块环境中,以便将其保存到湖中就好像它是普通文件夹一样:

with open('/dbfs/mnt/mydatalake/googleuserusagejsonoutput-{0}.json', 'wb') as f:
            json.dump(data, codecs.getwriter('utf-8')(f), sort_keys = True, indent = 4, ensure_ascii=False)
            f.close()

您只需要安装一次湖泊:

https://docs.databricks.com/spark/latest/data-sources/azure/azure-datalake-gen2.html#mount-the-azure-data-lake-storage-gen2-filesystem-with-dbfs

话虽这么说

以json格式存储大数据并不是最佳选择;对于要存储键(列名)的每个值(单元格),因此您的数据将远远大于所需的大小。另外,您可能应该具有重复数据删除功能,以确保这两个功能:(1)数据中没有间隙,(2)您没有将相同的数据存储在多个文件中。 Databricks delta可以解决这个问题。

https://docs.databricks.com/delta/delta-intro.html