

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

# 最佳化 CloudTrail Lake 查詢
<a name="lake-queries-optimization"></a>

此頁面提供如何最佳化 CloudTrail Lake 查詢以改善效能和可靠性的指引。它涵蓋了特定最佳化技術，以及常見查詢失敗的解決方法。

**Topics**
+ [最佳化查詢的建議](#lake-queries-tuning)
+ [查詢失敗的解決方法](#lake-queries-troubleshooting)

## 最佳化查詢的建議
<a name="lake-queries-tuning"></a>

請遵循本節中的建議，以最佳化您的查詢。

**Topics**
+ [最佳化彙總](#query-optimization-aggregation)
+ [使用近似技術](#query-optimization-approximation)
+ [限制查詢結果](#query-optimization-limit)
+ [最佳化 LIKE 查詢](#query-optimization-like)
+ [使用 `UNION ALL` 而非 `UNION`](#query-optimization-union)
+ [僅包含必填資料欄](#query-optimization-reqcolumns)
+ [減少視窗函數範圍](#query-optimization-windows)

### 最佳化彙總
<a name="query-optimization-aggregation"></a>

排除子`GROUP BY`句中的備援資料欄可以改善效能，因為較少的資料欄需要較少的記憶體。例如，在以下查詢中，我們可以在類似 的備援資料欄上使用 `arbitrary`函數`eventType`來改善效能。上的 `arbitrary`函數`eventType`用於從群組隨機挑選欄位值，因為值相同，不需要包含在 `GROUP BY`子句中。

```
SELECT eventName, eventSource, arbitrary(eventType), count(*) 
FROM $EDS_ID 
GROUP BY eventName, eventSource
```

您可以透過`GROUP BY`依唯一值計數 （基數） 的遞減順序排序 中的欄位清單，來改善`GROUP BY`函數的效能。例如，在取得每個類型的事件數量時 AWS 區域，可以使用 來改善效能`eventName`，在`GROUP BY`函數中`awsRegion`排序 而非 `awsRegion`，`eventName`因為 比 `eventName` 更唯一。 `awsRegion`

```
SELECT eventName, awsRegion, count(*) 
FROM $EDS_ID 
GROUP BY eventName, awsRegion
```

### 使用近似技術
<a name="query-optimization-approximation"></a>

每當計算不同值時不需要確切的值時，請使用[近似彙總函數](https://trino.io/docs/current/functions/aggregate.html#approximate-aggregate-functions)來尋找最常用的值。例如， [https://trino.io/docs/current/functions/aggregate.html#approx_distinct](https://trino.io/docs/current/functions/aggregate.html#approx_distinct)使用的記憶體比 操作少得多，而且執行速度比 `COUNT(DISTINCT fieldName)`操作快。

### 限制查詢結果
<a name="query-optimization-limit"></a>

如果查詢只需要範例回應，請使用 `LIMIT`條件將結果限制為少量資料列。否則，查詢會傳回大型結果，並花費更多時間來執行查詢。

`LIMIT` 搭配 使用 `ORDER BY`可以更快地提供最上方或最下方 N 記錄的結果，因為它可減少排序所需的記憶體量和時間。

```
SELECT * FROM $EDS_ID
ORDER BY eventTime 
LIMIT 100;
```

### 最佳化 LIKE 查詢
<a name="query-optimization-like"></a>

您可以使用 `LIKE` 來查找相符字串，但對於長字串而言，此為計算密集型。在大多數情況下，[https://trino.io/docs/current/functions/regexp.html#regexp_like](https://trino.io/docs/current/functions/regexp.html#regexp_like)函數是更快的替代方案。

通常，您可以透過錨定您要尋找的子字串來最佳化搜尋。例如，如果您正在尋找字首，最好使用 '`substr`%' 而非 '%`substr`%' 搭配 `LIKE` 運算子和 '^`substr`' 搭配 `regexp_like`函數。

### 使用 `UNION ALL` 而非 `UNION`
<a name="query-optimization-union"></a>

`UNION ALL` 和 `UNION` 是將兩個查詢的結果合併為一個結果，但`UNION`移除重複項目的兩種方式。 `UNION`需要處理所有記錄並尋找重複項目，這是記憶體和運算密集型，但`UNION ALL`操作相對快速。除非您需要重複記錄，否則請使用 `UNION ALL` 以獲得最佳效能。

### 僅包含必填資料欄
<a name="query-optimization-reqcolumns"></a>

如果您不需要資料欄，請不要將其包含在查詢中。查詢必須處理的資料越少，執行速度就越快。如果您有在最外部查詢`SELECT *`中執行的查詢，您應該將 `*` 變更為您需要的資料欄清單。

`ORDER BY` 子句會以排序順序傳回查詢的結果。排序大量資料時，如果沒有可用的必要記憶體，會將中繼排序結果寫入磁碟，這可能會減慢查詢執行速度。如果您並不需要對結果進行排序，請避免新增 `ORDER BY` 子句。此外，如果不需要的話，請避免`ORDER BY`將 新增至內部查詢。

### 減少視窗函數範圍
<a name="query-optimization-windows"></a>

[視窗函數](https://trino.io/docs/current/functions/window.html)會將其操作的所有記錄保留在記憶體中，以計算其結果。當視窗非常大時，視窗函數可能會耗盡記憶體。若要確保查詢在可用的記憶體限制內執行，請新增 `PARTITION BY`子句來減少視窗函數操作的視窗大小。

有時，具有視窗函數的查詢可以在沒有視窗函數的情況下重寫。例如，您可以使用彙總函數，例如 `row_number`或 `rank`，而不是使用 [https://trino.io/docs/current/functions/aggregate.html#max_by](https://trino.io/docs/current/functions/aggregate.html#max_by)或 [https://trino.io/docs/current/functions/aggregate.html#min_by](https://trino.io/docs/current/functions/aggregate.html#min_by)。

下列查詢會使用 尋找最近指派給每個 KMS 金鑰的別名`max_by`。

```
SELECT element_at(requestParameters, 'targetKeyId') as keyId, 
max_by(element_at(requestParameters, 'aliasName'), eventTime) as mostRecentAlias 
FROM $EDS_ID 
WHERE eventsource = 'kms.amazonaws.com' 
AND eventName in ('CreateAlias', 'UpdateAlias') 
AND eventTime > DATE_ADD('week', -1, CURRENT_TIMESTAMP) 
GROUP BY element_at(requestParameters, 'targetKeyId')
```

在此情況下， `max_by`函數會傳回具有群組內最新事件時間的記錄別名。與具有視窗函數的對等查詢相比，此查詢執行速度更快，而且使用的記憶體更少。

## 查詢失敗的解決方法
<a name="lake-queries-troubleshooting"></a>

本節提供常見查詢失敗的解決方法。

**Topics**
+ [查詢失敗，因為回應太大](#large-responses)
+ [查詢因資源耗盡而失敗](#exhausted-resources)

### 查詢失敗，因為回應太大
<a name="large-responses"></a>

如果回應太大而導致訊息 ，查詢可能會失敗`Query response is too large`。如果發生這種情況，您可以減少彙總範圍。

這類彙總函數`array_agg`可能會導致查詢回應中的至少一列非常大，導致查詢失敗。例如，使用 `array_agg(eventName)`而不是 `array_agg(DISTINCT eventName)`會因為所選 CloudTrail 事件中的重複事件名稱而大幅增加回應大小。

### 查詢因資源耗盡而失敗
<a name="exhausted-resources"></a>

如果在執行聯結、彙總和視窗函數等記憶體密集型操作期間沒有足夠的記憶體可用，則中繼結果會溢出到磁碟，但溢出會減慢查詢執行速度，並不足以防止查詢因 而失敗`Query exhausted resources at this scale factor`。您可以透過重試查詢來修正此問題。

如果上述錯誤即使在最佳化查詢後仍持續存在，您可以使用事件`eventTime`的 縮小查詢的範圍，並以原始查詢時間範圍的較小間隔多次執行查詢。