

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

# 性能改进的关键重点领域
<a name="emr-trino-performance-areas"></a>

Trino 最大程度地提高了查询并行度和内存优化。此架构具有很高灵活性，能够查询多个不同的数据来源，同时还能高效扩展。Trino 的关键性能改进领域包括下面列出的方面。

## 内存优化
<a name="emr-trino-performance-areas-optimization"></a>

Trino 中的内存管理对于实现高性能和稳定性至关重要，尤其是在运行大型复杂查询时。Trino 使用分布式内存模型。在此模型中，内存是在 Worker 节点之间分配的，用于处理任务、聚合、联接和其他操作。以下列表介绍了这些设置的集合：
+ **query.max-memory**：设置整个集群中单个查询可用的最大内存。这是一个硬性限制；如果查询超出此内存，则会失败。
+ **查询。 max-memory-per-node**— 定义查询在每个工作节点上可以消耗的最大内存。设置此项可确保任何单个查询都不会独占任何工作线程上的资源。
+ **JVM 堆大小**：这在 JVM 级别进行配置，它设置每个节点上 Trino 服务器进程的最大堆大小。**此值通常应大于与内存相关的配置（这是查询的总和。 max-memory-per-node**和**记忆。 heap-headroom-per-node**) 在 Trino 中以避免系统在 JVM 级别耗尽内存。
+ **记忆。 heap-headroom-per-node**— 指定要从非查询操作的 JVM 堆大小中省略的缓冲区内存量。这对于确保内部操作和垃圾回收有足够的开销至关重要。

## 动态筛选
<a name="emr-trino-performance-areas-dynamic"></a>

Trino 中的动态筛选是一种优化技术，它通过减少处理的数据量（尤其是在联接期间）来提高查询性能。它根据联接一侧看到的数据，动态应用筛选条件来限制联接另一侧扫描的数据，这在联接一侧具有高度选择性（这意味着它包含一小部分数据）的查询中特别有用。Amazon EMR 默认启用该功能。以下是查询示例：

```
SELECT orders.order_id, orders.total_amount
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id
WHERE customers.country = 'France';
```

如果没有动态筛选，Trino 会扫描联接中的整个订单表，即使只有一小部分客户（来自法国的客户）相关也是如此。这种方法会读取**订单**表中的所有行，从而导致高昂 I/O 的处理成本。借助动态筛选，Trino 首先扫描较小的**客户**表，仅检索法国客户的 customer\$1id 值，然后将此子集作为筛选条件应用于订单。这意味着只会扫描**订单**中的相关行（customer\$1id 与筛选后的子集匹配的行），从而大大减少处理的记录数。

## 溢出到磁盘
<a name="emr-trino-performance-areas-spill"></a>

 在 Trino 中，磁盘溢出允许将中间查询结果卸载到磁盘，从而使内存密集型查询能够完成，即使它们超过了 `query_max_memory` 或 `query_max_memory_per_node` 设置的内存限制也是如此。默认情况下，Trino 会强制执行这些限制，以确保内存分配保持公平并防止集群死锁。但是，当大型查询超过这些限制时，就会面临终止的风险。磁盘溢出使用 `revocable memory` 来解决此问题，允许查询借用额外的内存，如果其他地方需要资源，则可以撤销这些内存。当内存被撤销时，中间数据会溢出到磁盘，从而使查询能够继续处理而不会超出内存限制。请注意，强制溢出到磁盘的查询的执行时间可能会更长，因此此功能默认禁用。要在 Amazon EMR 上启用溢出，请使用下面的配置：
+ `spill-enabled=true`：当内存使用量超过可用阈值时，启用磁盘溢出。
+ `spill-paths`：定义存储溢出数据的目录 `spill-paths=/mnt/spill`。