

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 优化写入性能
<a name="best-practices-write"></a>

本节讨论表属性，您可以调整这些属性以优化 Iceberg 表的写入性能，不受引擎影响。

## 设置表格分发模式
<a name="write-distribution-mode"></a>

Iceberg 提供多种写入分配模式，用于定义写入数据在 Spark 任务中的分布方式。有关可用模式的概述，请参阅 Iceberg 文档中的[编写分发模式](https://iceberg.apache.org/docs/latest/spark-writes/#writing-distribution-modes)。

对于优先考虑写入速度的用例，尤其是在流式工作负载中，`write.distribution-mode`请设置为`none`。这样可以确保 Iceberg 不会请求额外的 Spark 洗牌，并且可以在 Spark 任务中可用时写入数据。此模式特别适用于 Spark 结构化流媒体应用程序。

**注意**  
将写入分配模式设置为`none`往往会生成大量小文件，从而降低读取性能。我们建议定期进行压缩，将这些小文件整合到大小合适的文件中，以提高查询性能。

## 选择正确的更新策略
<a name="write-update-strategy"></a>

当您的用例可以接受对最新数据执行较慢的读取操作时，请使用 merge-on-read****策略来优化写入性能。

使用时 merge-on-read，Iceberg 会将更新和删除内容作为单独的小文件写入存储器。读取表格时，读者必须将这些更改与基础文件合并，以返回最新的数据视图。这会导致读取操作的性能下降，但会加快更新和删除的写入速度。通常， merge-on-read对于具有更新的流式处理工作负载或更新较少且分布在多个表分区中的任务来说，它是理想的选择。

可以在表级别设置 merge-on-read配置（`write.update.mode``write.delete.mode`、和`write.merge.mode`），也可以在应用程序端单独设置。

使用 merge-on-read需要定期进行压缩，以防止读取性能随着时间的推移而下降。Compaction 可将更新和删除与现有数据文件进行协调，以创建一组新的数据文件，从而消除读取方面产生的性能损失。默认情况下，除非您将`delete-file-threshold`属性的默认值更改为较小的值，否则Iceberg的压缩不会合并删除文件（请参阅 [Iceberg](https://iceberg.apache.org/docs/latest/spark-procedures/#rewrite_data_files) 文档）。要了解有关压实的更多信息，请参阅本指南后面的[冰山压实](best-practices-compaction.md)部分。

## 选择正确的文件格式
<a name="write-file-format"></a>

Iceberg 支持以 Parquet、ORC 和 Avro 格式写入数据。镶木地板是默认格式。Parquet 和 ORC 是列式格式，可提供卓越的读取性能，但通常写入速度较慢。这代表了读取和写入性能之间的典型权衡。

如果写入速度对您的用例很重要，例如在流媒体工作负载中，请考虑在编写器的选项`Avro`中设置为`write-format`，以 Avro 格式写入。由于 Avro 是一种基于行的格式，因此它以较慢的读取性能为代价提供更快的写入时间。

要提高读取性能，请定期进行压缩，将小 Avro 文件合并并转换为较大的 Parquet 文件。压实过程的结果受制于`write.format.default`表格设置。Iceberg 的默认格式是 Parquet，因此，如果你用 Avro 编写然后运行压缩，Iceberg 会将 Avro 文件转换为 Parquet 文件。示例如下：

```
spark.sql(f"""
    CREATE TABLE IF NOT EXISTS glue_catalog.{DB_NAME}.{TABLE_NAME} (
        Col_1 float, 
        <<<…other columns…>>
        ts timestamp)
    USING iceberg
    PARTITIONED BY (days(ts))
    OPTIONS (
      'format-version'='2',
      write.format.default'=parquet)
""")

query = df \
    .writeStream \
    .format("iceberg") \
    .option("write-format", "avro") \
    .outputMode("append") \
    .trigger(processingTime='60 seconds') \
    .option("path", f"glue_catalog.{DB_NAME}.{TABLE_NAME}") \
    .option("checkpointLocation", f"s3://{BUCKET_NAME}/checkpoints/iceberg/")

    .start()
```