amazon-s3 - Databricks 中的显式表分区如何影响写入性能?

标签 amazon-s3 hive apache-spark-sql databricks delta-lake

我们有以下场景:

  • 我们有一个包含大约的现有表。 150 亿条记录。它在创建时没有明确分区。
  • 我们正在创建一个带有分区的表的副本,希望在某些类型的查询上有更快的读取时间。
  • 我们的表位于 Databricks Cloud 上,我们使用 Databricks Delta。
  • 我们通常按两列进行过滤,其中一列是实体的 ID(35 万个不同的值),另一列是事件发生的日期(到目前为止有 31 个不同的值,但每天都在增加!)。

  • 因此,在创建新表时,我们运行了如下查询:

    CREATE TABLE the_new_table
    USING DELTA
    PARTITIONED BY (entity_id, date)
    AS SELECT
      entity_id,
      another_id,
      from_unixtime(timestamp) AS timestamp,
      CAST(from_unixtime(timestamp) AS DATE) AS date
    FROM the_old_table
    

    此查询已运行 48 小时,并且还在继续。我们知道它正在取得进展,因为我们在相关的 S3 前缀中找到了与第一个分区键对应的大约 25 万个前缀,并且这些前缀中肯定存在一些大文件。

    但是,我们很难准确监控取得了多少进展,以及我们预计需要多长时间。

    在等待的过程中,我们尝试了这样的查询:

    CREATE TABLE a_test_table (
      entity_id STRING,
      another_id STRING,
      timestamp TIMESTAMP,
      date DATE
    )
    USING DELTA
    PARTITIONED BY (date);
    
    INSERT INTO a_test_table
    SELECT
      entity_id,
      another_id,
      from_unixtime(timestamp) AS timestamp,
      CAST(from_unixtime(timestamp) AS DATE) AS date
    FROM the_old_table
      WHERE CAST(from_unixtime(timestamp) AS DATE) = '2018-12-01'
    

    请注意此处新表架构的主要区别在于我们仅按日期分区,而不是按实体 id 分区。我们选择的日期几乎正好包含旧表数据的 4%,我想指出这一点,因为它远远超过 1/31。当然,由于我们通过一个恰好与我们分区的对象相同的值进行选择,因此我们实际上只写入了一个分区,而可能是十万左右。

    使用相同数量的工作节点创建此测试表需要 16 分钟,因此我们预计(基于此)创建 25 倍大的表只需大约 7 小时 .

    This answer似乎部分承认使用过多的分区会导致问题,但在过去几年中,根本原因似乎发生了很大变化,因此我们试图了解当前的问题可能是什么; Databricks docs没有特别有启发性。

    基于发布的 request rate guidelines for S3 ,似乎增加分区(键前缀)的数量应该可以提高性能。有害的分区似乎违反直觉。

    总结:我们期望将数千条记录写入数千个分区中的每一个。似乎减少分区数量会显着减少写入表数据所需的时间。为什么这是真的?对于应该为特定大小的数据创建的分区数量,是否有任何一般准则?

    最佳答案

    您应该按 date 对数据进行分区因为这听起来像是随着时间的流逝而不断添加数据。这是对时间序列数据进行分区的普遍接受的方法。这意味着您将每天写入一个日期分区,并且您之前的日期分区不会再次更新(一件好事)。

    如果您的用例从中受益,您当然可以使用辅助分区键(即 PARTITIONED BY (date, entity_id) )

    按日期分区将需要您始终按日期读取此数据,以获得最佳性能。如果这不是您的用例,那么您必须澄清您的问题。

    多少个分区?

    没有人可以回答您应该使用多少个分区,因为每个数据集(和处理集群)都是不同的。您想要避免的是“数据倾斜”,即一名工作人员不得不处理大量数据,而其他工作人员则处于空闲状态。在你的情况下,如果一个 clientid 就会发生这种情况例如,是数据集的 20%。按日期分区必须假设每天有大致相同的数据量,因此每个工作人员都保持同样的忙碌。

    我不知道 Databricks 如何写入磁盘,但在 Hadoop 上,我希望看到每个工作节点写入自己的文件部分,因此您的写入性能在这个级别上是并行的。

    关于amazon-s3 - Databricks 中的显式表分区如何影响写入性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54837662/

    相关文章:

    javascript - 从客户端下载AWS S3文件

    swift - 使用 Alamofire.upload(...) 将 NSData 从 S3 放入 PreSigned URL 在 iOS 8 上不起作用

    hadoop - HIVE中的期间数据类型支持到TERADATA导出

    读取 Hive 表中的 JSON 数据

    scala - 嵌套 DataFrame 数组中的元素位置 (Spark 2.2)

    python - 仅从 pyspark 中的 Spark DF 选择数字/字符串列名称

    java - AWS S3 和手机架构

    amazon-web-services - Grails AWS SDK 插件无法解析 PutObjectRequest

    database - HiveQL到HBase

    python - 当值相同但情况不同时,Spark 数据帧透视失败