Databricks 上的 Spark - 缓存 Hive 表
Posted
技术标签:
【中文标题】Databricks 上的 Spark - 缓存 Hive 表【英文标题】:Spark on Databricks - Caching Hive table 【发布时间】:2018-03-19 14:25:33 【问题描述】:我们在 S3 上的 parquet 文件中存储了事实表(30 列),并在此文件上创建了表并随后将其缓存。使用此代码 sn-p 创建表:
val factTraffic = spark.read.parquet(factTrafficData)
factTraffic.write.mode(SaveMode.Overwrite).saveAsTable("f_traffic")
%sql CACHE TABLE f_traffic
我们在此表(文件)上运行许多不同的计算,并正在寻找缓存数据的最佳方法,以便在后续计算中更快地访问。问题是,由于某种原因,从 parquet 读取数据并进行计算然后从内存中访问它会更快。一个重要的注意事项是我们不会利用每一列。通常,每次计算大约 6-7 列,并且每次使用不同的列。
有没有办法将此表缓存在内存中,以便我们可以比从 parquet 读取更快地访问它?
【问题讨论】:
【参考方案1】:听起来您在 Databricks 上运行,因此您的查询可能会自动受益于 Databricks IO Cache。来自 Databricks docs:
Databricks IO 缓存通过使用快速中间数据格式在节点的本地存储中创建远程文件的副本来加速数据读取。每当必须从远程位置获取文件时,数据都会自动缓存。然后在本地执行相同数据的连续读取,从而显着提高读取速度。
Databricks IO 缓存支持从 DBFS、Amazon S3、HDFS、Azure Blob 存储和 Azure Data Lake 读取 Parquet 文件。不支持CSV、JSON、ORC等其他存储格式。
Databricks Runtime 3.3 或更高版本支持 Databricks IO 缓存。默认情况下是否启用取决于您为集群上的工作程序选择的实例类型:目前它为 Azure Ls 实例和 AWS i3 实例自动启用(请参阅 Databricks 文档的 AWS 和 Azure 版本完整的细节)。
如果这个 Databricks IO 缓存正在生效,那么显式使用带有未转换基表的 Spark 的 RDD 缓存可能会损害查询性能,因为它将存储数据的第二个冗余副本(并支付往返解码和编码以便执行所以)。
如果您正在缓存转换后的数据集,例如,显式缓存仍然可以使用。经过过滤以显着减少数据量,但如果您只想缓存大型且未转换的基本关系,那么我个人建议依靠 Databricks IO 缓存并避免使用 Spark 的内置 RDD 缓存。
有关更多详细信息,请参阅完整的 Databricks IO 缓存文档,包括有关缓存预热、监控以及 RDD 和 Databricks IO 缓存比较的信息。
【讨论】:
【参考方案2】:缓存中的数据帧,你应该这样做:
val factTraffic = spark.read.parquet(factTrafficData)
factTraffic.write.mode(SaveMode.Overwrite).saveAsTable("f_traffic")
val df_factTraffic = spark.table("f_traffic").cache
df_factTraffic.rdd.count
// now df_factTraffic is materalized in memory
另见https://***.com/a/42719358/1138523
但这是否有意义值得怀疑,因为 parquet 是一种列文件格式(这意味着投影非常有效),如果您需要为每个查询使用不同的列,缓存将无济于事。
【讨论】:
Projection 对 S3 或其他云存储的效率不如对 HDFS 的有效,因为如果您需要中止 HTTP GET 并开始一个新的,则 seek 非常昂贵。如果您不使用缓存,则需要检查 databricks 中的 S3A 客户端是否支持 fs.s3a.experimental.fadvise=random 选项,然后在处理 parquet 数据时设置它,但在工作时不支持使用 CSV 或 .gz 文件 “f_traffic”是磁盘上的文件吗?以上是关于Databricks 上的 Spark - 缓存 Hive 表的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spark Databricks 中注册 SQL 函数
获取 TypeError:在 Apache Spark / Databricks 中尝试流数据时,路径只能是单个字符串