

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

# 扩展 Trino 工作负载时面临的常见挑战
<a name="emr-trino-common-issues"></a>

将 Amazon S3 与 Trino 结合使用的主要优势在于 S3 能够针对大量数据进行扩展以及 S3 的成本效益。但是，当您查询大量数据时，偶尔会发生一系列性能相关的问题。这些问题可能是由于数据存储方式、限制良好性能的配置设置或其他原因造成的。当这些问题发生时，您可以采取有效的措施来避免或缓解它们。

本节首先列出了您要提高大量数据的查询性能而可以实施的常规优化。接下来将详细介绍常见问题，并针对每个问题提供了缓解措施。

本主题源自以下会议演讲：[Accelerate performance at scale: Best practices for Trino with Amazon S3](https://www.youtube.com/watch?v=cjUUcHlUKxQ)。

## 优化大型数据集的数据布局
<a name="emr-trino-common-issues-practices"></a>

查询大型数据集时，性能瓶颈并不罕见。但是，在使用 Trino 查询 Amazon S3 中的数据时，您可以实施一些最佳实践来快速上手。这些功能包括：
+ **分区**：分区是指按层次结构组织数据，并基于相关属性存储相关数据。分区使查询无需扫描不相关数据，从而提高查询性能。您可以使用各种分区策略，例如使用前缀排列源数据，特别是按日期范围、区域或其他属性进行排列。有关在 Amazon S3 中对数据进行分区以提高性能的更多详细信息，请参阅博客文章《[开始管理由 Gl Amazon ue 数据目录支持的 Amazon S3 表的分区](https://www.amazonaws.cn/blogs/big-data/get-started-managing-partitions-for-amazon-s3-tables-backed-by-the-aws-glue-data-catalog/)》或文章《[十大性能调整技巧](https://www.amazonaws.cn/blogs/big-data/top-10-performance-tuning-tips-for-amazon-athena/)》。 Amazon Athena
+ **分桶**：分桶是将相关数据分组到公共文件中。例如，如果您按地理区域（例如州）查询数据，则可以将特定州的所有数据分组到同一个文件或文件组中，从而提高查询性能。为了使其发挥最佳效果，请基于具有高基数的数据属性（例如州或省）进行分桶。此外，您还可以考虑查询模式。例如，如果您的查询通常同时读取加利福尼亚州和俄勒冈州的数据，则可以将这两个州的数据分组在一起。
+ **管理 S3 前缀**：您可以使用 Amazon S3 前缀来实现分区策略。如果您对 Amazon S3 存储桶仅使用单个前缀（例如特定日期），则可能会产生大量请求，并可能导致 HTTP 503 错误。我们建议使用前缀来添加额外的条件，并更有效地组织源数据。有关更多信息，请参阅 Amazon S3 文档中的[使用前缀组织对象](https://docs.amazonaws.cn/AmazonS3/latest/userguide/using-prefixes.html)。以下简短示例展示了一种可以提高请求吞吐量的前缀：`s3://bucket/country=US/dt=2024-06-13`。在此示例中，前缀中包含了国家/地区和日期，因此读取次数比前缀仅包含日期的情况要少。

  本主题接下来的 *HTTP 速度变慢*部分将更详细地讨论如何缓解 HTTP 503 错误。
+ **优化数据大小**：您可以运行 OPTIMIZE 命令来设置有利于提升查询性能的配置。要针对 Hive 外部表运行此命令，请按照以下步骤进行操作：
  + 使用 `OPTIMIZE` 和以下参数：`hive.non-managed-table-writes-enabled=true`。有关此属性的更多信息，请参阅 [Hive general configuration properties](https://trino.io/docs/current/connector/hive.html#hive-general-configuration-properties)。
  + 设置以下会话参数：`SET SESSION` `{{catalog}}.non_transactional_optimize_enabled=true`
  + 运行 `OPTIMIZE` 命令：`ALTER TABLE {{catalog}}.{{schema}}.{{table}} EXECUTE optimize(file_size_threshold => '128MB')`。在本例中，`file_size_threshold` 默认为 100 MB。如示例所示，提高此阈值将导致小于 128 MB 的文件被合并。
+ **配置重试次数**：您可以通过设置 `s3.max-error-retries` 来增加重试次数限制，从而降低出现 HTTP 503 错误的概率。这适用于您使用 TrinoFileSystem API 和 Trino 449 或更高版本的情况。另一方面，如果您将 Amazon EMR 与 Trino 结合使用，请使用 EMRFS 来访问 Amazon S3。使用 EMRFS，您可以通过更改 `fs.s3.maxRetries` 参数来增加重试次数。
+ **选择 Amazon S3 存储类别**：根据您对特定数据收集的要求，在数据生命周期的不同阶段选择合适的存储类别有助于提高性能并降低成本。有关更多信息，请参阅 Amazon S3 文档中的[了解和管理 Amazon S3 存储类别](https://docs.amazonaws.cn/AmazonS3/latest/userguide/storage-class-intro.htm)。
+ **迁移到 Iceberg**：另一个缓解性能问题（特别是针对小文件运行查询）的解决方案是迁移到 Iceberg 表。Iceberg 具有可以很好地处理小文件的功能。
+ **使用自动数据压缩** — 如果您使用 Iceberg 表，则使用 Glue 数据目录 Amazon 进行自动数据压缩可以优化数据大小并提高查询性能。

## 查询大型数据集时面临的常见挑战
<a name="emr-trino-common-issues-challenges"></a>

本节列出了在 Amazon S3 中积累大型数据集并使用 Trino 查询时可能出现的一系列常见问题。每个章节都会介绍解决问题或降低其对查询影响的方法。以下各节中描述的每个问题都已使用 Hive 连接器重现和测试。

### 大型数据扫描
<a name="emr-trino-common-issues-large-scan"></a>

当查询需要扫描大型数据集时，可能会导致查询性能下降和存储成本增加等问题。数据量庞大可能是快速数据增长或规划引起的，这导致无法在适当的时间范围内移动传统数据。这会导致查询速度变慢。

为了减轻扫描大型数据集带来的性能损失，我们建议您使用分区和分桶：
+ 分区根据数据属性将相关数据分组在一起。有效利用分区可以显著提升查询性能。
+ 分桶根据特定相关的数据列将数据分组到文件或存储桶中。分桶通常意味着以物理方式将相关源数据文件放在一起。

为了说明缓解措施如何适用于大型数据扫描，假设您存储和查询的数据包含具有州属性的记录，该属性可以分配给加利福尼亚州或阿拉斯加州，而此州属性是您的查询条件之一。您可以通过将每个州的数据存储在单独的 S3 存储桶中，或者使用 S3 前缀按州对数据进行分区来提高查询性能。如果基于额外列（例如日期属性）进行分区和分桶，则此分区和分桶还可以提高性能。

**注意**  
如果某一列的基数很高，并且你想使用它来对数据进行分组，我们建议在这种情况下使用分桶。另一方面，通常，分区键的基数应该较低。

**使用各种 S3 存储类型**

通常，您会根据工作负载的性能、数据访问、弹性和成本要求来选择存储类型。成本和性能之间可能需要权衡。选择与您的数据访问模式匹配的合适 Amazon S3 存储类别至关重要。有两种主要访问模式：
+ 以已知或可预测的方式访问的数据。通常，如果您的数据不经常访问，S3 标准 IA 是一个不错的选择，因为它有助于降低成本。如果您的数据访问频率很高，则 S3 标准最适合使用 Amazon EMR 和 Trino 访问。
+ 以未知或不可预测的方式访问的数据。这可能需要使用其他 Amazon S3 存储类别，S3 存储类别之间存在权衡取舍。其中包括延迟、存储成本和可用性。您可以根据工作负载和访问模式选择合适的 S3 存储类型。有关每个类别的优势的描述，请参阅 [Amazon S3 存储类别]()。

**使用压缩**

如果您使用 Iceberg 表，则还可以使用 Iceberg 自动压缩，从而获得更优化的文件大小，以提高查询效率。有关更多信息，请参阅 [Amazon Glue Data Catalog now supports automatic compaction of Apache Iceberg tables](https://www.amazonaws.cn/blogs/aws/aws-glue-data-catalog-now-supports-automatic-compaction-of-apache-iceberg-tables/)。

### HTTP 减慢速度错误
<a name="emr-trino-common-issues-slow-network"></a>

当 Amazon S3 前缀的请求速率超过预配置的阈值时，就会发生这种情况。达到此状态时最常发生的 HTTP 错误如下：**错误 503：请降低请求速率**。此问题的根源可能在于存在大量小文件，因为读取数据必须创建大量*拆分*。有几种方法可以缓解该问题：
+ 增加 Trino 中 Amazon S3 请求的重试次数限制。这是在 Trino 449 中使用 `fs.s3.maxretries` 为 EMRFS 设置的。
+ 优化文件大小，这也可以降低请求频率。

有关 Trino 如何确定要查询的数据集中的拆分数量的更多信息，请参阅 Hive 连接器文档中的 [Performance tuning configuration properties](https://trino.io/docs/current/connector/hive.html#performance-tuning-configuration-properties)。

### 查询小文件时遇到困难
<a name="emr-trino-common-issues-small-files"></a>

由于大量的 GET 和 LIST 请求，查询许多小文件可能会导致大量 I/O 开销，进而对查询性能产生负面影响。优化文件大小可以提高查询性能。有几种方法可以做到这一点：
+ 将数据整合到较少的大文件中。（通常，我们建议将文件大小保持在 128 MB 左右。） 您可以在摄取数据时使用工具（例如在 ETL 管道中）完成此操作，也可以手动整合数据。如果这些解决方案对您来说都不适用，则剩下方案可能更适合您。
+ 运行 `OPTIMIZE` 命令。
+ 设置 `SESSION` 参数。

请注意，Iceberg 具有一项将小文件合并成大文件的功能，即自动压缩。它适用于使用 Glue 数据 Amazon 目录管理的文件。有关更多信息，请参阅 [Amazon Glue Data Catalog now supports automatic compaction of Apache Iceberg tables](https://www.amazonaws.cn/blogs/aws/aws-glue-data-catalog-now-supports-automatic-compaction-of-apache-iceberg-tables/)。

### 包含不需要的数据的查询
<a name="emr-trino-common-issues-uneeded-data"></a>

数据增长是常态，因此必须跟踪数据访问模式，并在数据老化或变得无关紧要时适当地移动数据。这是因为随着数据增长，查询性能会随着时间推移而下降，这主要是因为查询运行时需要扫描的数据量非常庞大。Amazon S3 和其他服务为数据生命周期迁移提供了指导，展示了在数据变冷时将数据移动到不同存储位置的策略。这样做还可以节省存储成本。

除了数据迁移之外，您还可以使用其他策略，例如移除与正在运行的查询无关的源数据。这可能需要一些工作，因为它可能意味着要更改源数据架构。但它的积极效果是减少数据量，从而加快查询速度。有关更多信息，请参阅[管理对象的生命周期](https://docs.amazonaws.cn/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)。