

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 最佳化讀取效能
<a name="best-practices-read"></a>

本節討論您可以調校的資料表屬性，以最佳化讀取效能，不受引擎影響。

## 分割
<a name="read-partitioning"></a>

如同 Hive 資料表，Iceberg 使用分割區做為索引的主要層，以避免讀取不必要的中繼資料檔案和資料檔案。資料欄統計資料也會納入考量，做為索引的輔助層，以進一步改善查詢規劃，進而改善整體執行時間。

### 分割您的資料
<a name="read-partitioning-data"></a>

若要減少查詢 Iceberg 資料表時掃描的資料量，請選擇符合您預期讀取模式的平衡分割區策略：
+ 識別查詢中經常使用的資料欄。這些是理想的分割候選項目。例如，如果您通常查詢特定日期的資料，分割區資料欄的自然範例會是日期資料欄。
+ 選擇低基數分割區資料欄，以避免建立過多分割區。太多分割區可能會增加資料表中的檔案數量，這可能會對查詢效能產生負面影響。根據經驗法則，「太多分割區」可定義為大多數分割區中的資料大小小於 所設定值的 2-5 倍的情況`target-file-size-bytes`。

**注意**  
如果您通常會在高基數資料欄 （例如，可以有數千個值的資料`id`欄） 上使用篩選條件進行查詢，請使用 Iceberg 的隱藏分割功能與儲存貯體轉換，如下一節所述。

### 使用隱藏的分割
<a name="read-partitioning-hidden"></a>

如果您的查詢通常會篩選資料表資料欄的衍生項目，請使用隱藏的分割區，而不是明確建立新的資料欄以做為分割區。如需此功能的詳細資訊，請參閱 [Iceberg 文件](https://iceberg.apache.org/docs/latest/partitioning/#icebergs-hidden-partitioning)。

例如，在具有時間戳記資料欄 （例如，`2023-01-01 09:00:00`) 的資料集中，使用分割區轉換從時間戳記擷取日期部分，並即時建立這些分割區，而不是建立具有剖析日期的新資料欄 （例如，`2023-01-01`)。

隱藏分割最常見的使用案例為：
+ 當資料具有時間戳記資料欄時，**依日期或時間進行分割**。Iceberg 提供多種轉換，以擷取時間戳記的日期或時間部分。
+ **當分割資料欄具有高基數且會導致太多分割區時，對資料欄的雜湊函數**進行分割。Iceberg 的儲存貯體轉換會使用分割區欄上的雜湊函數，將多個分割區值分組為較少的隱藏 （儲存貯體） 分割區。

如需所有可用[分割區轉換](https://iceberg.apache.org/spec/#partition-transforms)的概觀，請參閱 Iceberg 文件中的分割區轉換。

用於隱藏分割的資料欄可透過使用 `year()`和 等一般 SQL 函數，成為查詢述詞的一部分`month()`。述詞也可以與 `BETWEEN`和 等運算子結合`AND`。

**注意**  
Iceberg 無法對產生不同資料類型的函數執行分割區剔除；例如，`substring(event_time, 1, 10) = '2022-01-01'`。

### 使用分割區演變
<a name="read-partitioning-evolution"></a>

當現有的[分割區策略不最佳時，請使用 Iceberg 的分割區演變](https://iceberg.apache.org/docs/latest/evolution/#partition-evolution)。例如，如果您選擇每小時分割區太小 （每個分割區只有幾個 MB)，請考慮轉換為每日或每月分割區。

當資料表的最佳分割區策略一開始不清楚，而且您想要在獲得更多洞見時精簡分割區策略時，您可以使用此方法。分割區演變的另一個有效用途是資料磁碟區變更，且目前的分割區策略會隨著時間而變得較不有效。

如需如何發展分割區的說明，請參閱 Iceberg 文件中的 [ALTER TABLE SQL 延伸](https://iceberg.apache.org/docs/latest/spark-ddl/#alter-table-sql-extensions)。 

## 調校檔案大小
<a name="read-file-size"></a>

最佳化查詢效能涉及將資料表中的小型檔案數量降至最低。為了獲得良好的查詢效能，我們通常建議將 Parquet 和 ORC 檔案保留大於 100 MB。

檔案大小也會影響 Iceberg 資料表的查詢規劃。隨著資料表中的檔案數量增加，中繼資料檔案的大小也會增加。較大的中繼資料檔案可能會導致較慢的查詢規劃。因此，當資料表大小增加時*，*請增加檔案大小** **以減輕中繼資料的指數擴展。

使用下列最佳實務，在 Iceberg 資料表中建立適當大小的檔案。

### 設定目標檔案和資料列群組大小
<a name="read-file-size-target"></a>

Iceberg 提供下列關鍵組態參數來調校資料檔案配置。我們建議您使用這些參數來設定目標檔案大小和資料列群組或執行大小。


| **Parameter (參數)** | **預設值** | **註解** | 
| --- |--- |--- |
| `write.target-file-size-bytes` | 512 MB | 此參數指定 Iceberg 將建立的檔案大小上限。不過，某些檔案的寫入大小可能會小於此限制。 | 
| `write.parquet.row-group-size-bytes` | 128 MB | Parquet 和 ORC 都會將資料存放在區塊中，以便引擎可以避免讀取某些操作的整個檔案。 | 
| `write.orc.stripe-size-bytes` | 64 MB | 
| `write.distribution-mode` | 無，適用於 Iceberg 1.1 版和更低版本雜湊，從 Iceberg 1.2 版開始 | Iceberg 會請求 Spark 在寫入儲存體之前排序其任務之間的資料。 | 
+ 根據您預期的資料表大小，請遵循下列一般準則：
  + **小型資料表** （最多幾個 GB) – 將目標檔案大小縮減至 128 MB。同時減少資料列群組或條紋大小 （例如 8 或 16 MB)。
  + **中大型資料表** （從幾 GB 到數百 GB) – 預設值是這些資料表的良好起點。如果您的查詢非常選擇性，請調整資料列群組或條紋大小 （例如，調整為 16 MB)。
  + **非常大的資料表** （數百 GB 或 TB) – 將目標檔案大小增加到 1024 MB 或更多，如果您的查詢通常提取大量資料集，請考慮增加資料列群組或條紋大小。
+ 若要確保寫入 Iceberg 資料表的 Spark 應用程式建立適當大小的檔案，請將 `write.distribution-mode` 屬性設定為 `hash`或 `range`。如需這些模式之間差異的詳細說明，請參閱 Iceberg 文件中的[撰寫分佈模式](https://iceberg.apache.org/docs/latest/spark-writes/#writing-distribution-modes)。

這些是一般準則。建議您執行測試，以識別特定資料表和工作負載最合適的值。

### 執行定期壓縮
<a name="read-file-size-compaction"></a>

上表中的組態會設定寫入任務可建立的檔案大小上限，但不保證檔案會有該大小。為了確保適當的檔案大小，請定期執行壓縮，將小型檔案合併成較大的檔案。如需執行壓縮的詳細指引，請參閱本指南稍後的 [Iceberg 壓縮](best-practices-compaction.md)。

## 最佳化資料欄統計資料
<a name="read-column-statistics"></a>

Iceberg 使用資料欄統計資料來執行檔案刪除，透過減少查詢掃描的資料量來改善查詢效能。若要受益於資料欄統計資料，請確定 Iceberg 會收集查詢篩選條件中常用的所有資料欄統計資料。

根據預設，Iceberg 只會收集[每個資料表中前 100 個資料欄](https://github.com/apache/iceberg/blob/ae15c7e36973501b40443e75816d3eac39eddc90/core/src/main/java/org/apache/iceberg/TableProperties.java#L276)的統計資料，如資料表屬性 所定義`write.metadata.metrics.max-inferred-column-defaults`。如果您的資料表有超過 100 個資料欄，而且您的查詢經常參考前 100 個資料欄以外的資料欄 （例如，您可能有篩選資料欄 132 的 查詢），請確定 Iceberg 收集這些資料欄的統計資料。有兩種選項可達成此目標：
+ 當您建立 Iceberg 資料表時，請重新排序資料欄，以便查詢所需的資料欄落在 設定的資料欄範圍內 `write.metadata.metrics.max-inferred-column-defaults`（預設為 100)。

  注意：如果您不需要 100 個資料欄的統計資料，您可以將`write.metadata.metrics.max-inferred-column-defaults`組態調整為所需的值 （例如 20) 並重新排序資料欄，以便您需要讀取和寫入查詢的資料欄落在資料集左側的前 20 個資料欄內。
+ 如果您在查詢篩選條件中只使用幾個資料欄，您可以停用指標收集的整體屬性，並選擇性地選擇要收集統計資料的個別資料欄，如本範例所示：

  ```
  .tableProperty("write.metadata.metrics.default", "none")
  .tableProperty("write.metadata.metrics.column.my_col_a", "full")
  .tableProperty("write.metadata.metrics.column.my_col_b", "full")
  ```

注意：當資料對這些資料欄進行排序時，資料欄統計資料最有效。如需詳細資訊，請參閱本指南稍後的設定[排序順序](#read-sort-order)一節。

## 選擇正確的更新策略
<a name="read-update"></a>

當您的使用案例接受較慢的寫入操作時，請使用copy-on-write策略來最佳化讀取效能。這是 Iceberg 使用的預設策略。

Copy-on-write可提高讀取效能，因為檔案是以讀取最佳化的方式直接寫入儲存體。不過，相較於merge-on-read，每個寫入操作需要更長的時間，並耗用更多運算資源。這提供了讀取和寫入延遲之間的傳統取捨。一般而言，copy-on-write非常適合大多數更新共置於相同資料表分割區 （例如，用於每日批次載入） 的使用案例。

Copy-on-write組態 (`write.update.mode`、 `write.delete.mode`和 `write.merge.mode`) 可以在資料表層級設定，或在應用程式端獨立設定。

## 使用 ZSTD 壓縮
<a name="read-compression"></a>

您可以使用資料表屬性 修改 Iceberg 使用的壓縮轉碼器`write.<file_type>.compression-codec`。我們建議您使用 ZSTD 壓縮轉碼器來改善資料表的整體效能。

根據預設，Iceberg 1.3 版和更早版本使用 GZIP 壓縮，相較於 ZSTD，其提供較慢的讀取/寫入效能。

注意：某些引擎可能會使用不同的預設值。對於[使用 Athena 或 Amazon EMR 7.x 版建立的 Iceberg 資料表](https://docs.aws.amazon.com/athena/latest/ug/compression-support-iceberg.html)，這是這種情況。

## 設定排序順序
<a name="read-sort-order"></a>

為了改善 Iceberg 資料表的讀取效能，建議您根據查詢篩選條件中常用的一或多個資料欄來排序資料表。排序結合 Iceberg 的資料欄統計資料，可大幅提高檔案剔除的效率，進而加快讀取操作。排序也會減少在查詢篩選條件中使用排序資料欄之查詢的 Amazon S3 請求數量。

您可以使用 Spark 執行資料定義語言 (DDL) 陳述式，在資料表層級設定階層排序順序。如需可用選項，請參閱 [Iceberg 文件](https://iceberg.apache.org/docs/latest/spark-ddl/#alter-table--write-ordered-by)。設定排序順序後，寫入器會將此排序套用至 Iceberg 資料表中的後續資料寫入操作。

例如，在大部分查詢依 篩選的日期 (`yyyy-mm-dd`) 分割的資料表中`uuid`，您可以使用 DDL 選項來`Write Distributed By Partition Locally Ordered`確保 Spark 寫入具有非重疊範圍的檔案。

下圖說明排序資料表時，資料欄統計資料的效率如何改善。在此範例中，排序的資料表只需要開啟單一檔案，並從 Iceberg 的分割區和檔案獲得最大效益。在未排序的資料表中，任何 `uuid` 都可能存在於任何資料檔案中，因此查詢必須開啟所有資料檔案。

![\[在 Iceberg 資料表中設定排序順序\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/apache-iceberg-on-aws/images/setting-sort-order.png)


變更排序順序不會影響現有的資料檔案。您可以使用 Iceberg 壓縮來套用排序順序。

使用 Iceberg 排序資料表可能會降低工作負載的成本，如下圖所示。

![\[Iceberg 和 Parquet 資料表的比較成本\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/apache-iceberg-on-aws/images/cost-graph.png)


這些圖表摘要了執行 Hive (Parquet) 資料表與 Iceberg 排序資料表的 TPC-H 基準測試的結果。不過，其他資料集或工作負載的結果可能不同。

![\[Parquet 與 Iceberg 資料表的 TPC-H 基準結果\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/apache-iceberg-on-aws/images/s3-api-calls.png)
