在增量表中存储我的数据帧时,为我的数据帧寻找有效的分区策略。
我当前的数据帧 1.5000.000 rowa 将数据从数据帧移动到增量表需要 3.5 小时。
为了寻找更有效的写作方式,我决定尝试将我的表的不同列作为分区列。我搜索了我的列的基数并选择了以下列。
column1 = 有 3 个 distinct_values
column2 = 有 7 个不同的值
column3 = 有 26 个不同的值
column4 = 有 73 个不同的值
column5 = 有 143 个不同的值
column6 = 有 246 个不同的值
column7 = 有 543 个不同的值
集群:64GB,8核
在我的笔记本中使用以下代码
df.write.partitionBy("column_1").format("delta").mode("overwrite").save(partition_1)
..
df.write.partitionBy("column_7").format("delta").mode("overwrite").save(partition7)
因此,我想看看哪种分区策略会带来更好的结果:具有高基数的列、具有低基数的列或介于两者之间的列。 令我惊讶的是,这并没有产生任何影响,因为它几乎花费了所有时间,只是相差几分钟,但所有时间都为 + 3 小时。
为什么我失败了?分区没有优势吗?
最佳答案
当您使用 Delta(Databricks 或 OSS Delta 1.2.x,更好的 2.0)时,通常您可能根本不需要使用分区,原因如下(不适用于 Parquet 或其他文件格式):
- Delta 支持 data skipping允许只读取必要的文件,当您将它与 OPTIMIZE ZORDER BY 结合使用时尤其有效这将使相关数据彼此更接近。
- Bloom filters允许更精细地跳过文件。
对 Delta 湖表使用分区的经验法则如下:
- 在有利于查询时使用它,尤其是当您对表执行 MERGE 时,因为它可以避免并行事务之间的冲突
- 当它有助于删除旧数据时(例如按日期分区)
- 当它真正有益于您的查询时。例如,您有每个国家/地区的数据,并且大多数查询将使用国家/地区作为条件的一部分。或者例如,当您按日期分区,并根据时间查询数据时...
在所有情况下,不要对高基数列(数百个值)和分区列太多使用分区,因为在大多数情况下,这会导致创建读取效率较低的小文件(每个文件单独访问) ),加上它会增加驱动程序的负载,因为它需要为每个文件保留元数据。
关于delta-lake - 如何有效地对 Delta 表进行分区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73094038/