在 Athena 中分割和歸納 - Amazon Athena

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

在 Athena 中分割和歸納

分割和歸納是減少執行查詢時 Athena 必須掃描的資料量的兩種方法。分割和歸納互為補充,且可搭配使用。減少掃描的資料量可改善查詢效能並降低成本。如需有關 Athena 查詢效能的一般指導方針,請參閱 Amazon Athena 的十大效能調校秘訣

什麼是分割?

分割表示根據資料的特定屬性,將資料整理到 Amazon S3 上的目錄 (或「字首」)。這類屬性稱為分割區索引鍵。常見的分割區索引鍵是日期或一些其他時間單位,例如年份或月份。不過,資料集可以依多個索引鍵進行分割。例如,有關產品銷售的資料可能依日期、產品類別和市場進行分割。

決定如何分割

分割區索引鍵的理想候選者是始終或經常在查詢中使用且具有低基數的屬性。分割區過多和分割區過少之間需要取得權衡。由於分割區過多,檔案數增加會產生負荷。篩選分割區本身也有一些負荷。如果分割區太少,查詢通常需要掃描更多資料。

建立分割的資料表

分割資料集後,您可以在 Athena 建立分割的資料表。分割的資料表是具有分割區索引鍵的資料表。使用 CREATE TABLE 時,您可以將分割區新增至資料表中。使用 CREATE TABLE AS 時,在 Amazon S3 上建立的分割區會自動新增至資料表。

CREATE TABLE 陳述式中,您可以在 PARTITIONED BY (column_name data_type) 子句中指定分割區索引鍵。在 CREATE TABLE AS 陳述式中,您可以在 WITH (partitioned_by = ARRAY['partition_key']) 子句或 Iceberg 資料表的 WITH (partitioning = ARRAY['partition_key']) 中指定分割區索引鍵。出於效能考量,分割區索引鍵應始終是類型 STRING。如需詳細資訊,請參閱 使用字串做為分割區索引鍵的資料類型

如需其他 CREATE TABLECREATE TABLE AS 語法詳細資訊,請參閱 CREATE TABLECTAS 資料表屬性

查詢分割的資料表

當您查詢分割區資料表時,Athena 會使用查詢中的述詞來篩選分割區的清單。然後,其會使用相符分割區的位置來處理找到的檔案。Athena 只要不讀取與查詢述詞不相符的分割區中的資料,就能有效減少掃描的資料量。

範例

假設您有一個依 sales_dateproduct_category 分割的資料表,並且想知道特定類別中一周的總收入。您可以在 sales_dateproduct_category 資料欄上加入述詞,以確保 Athena 只掃描最少量的資料,如下列範例所示。

SELECT SUM(amount) AS total_revenue FROM sales WHERE sales_date BETWEEN '2023-02-27' AND '2023-03-05' AND product_category = 'Toys'

假設您有依日期分割的資料集,但也有精細的時間戳記。

使用 Iceberg 資料表,您可以宣告分割區索引鍵與資料欄之間的關係,但是使用 Hive 資料表時,查詢引擎對資料欄和分割區索引鍵之間的關係一無所知。因此,您必須在查詢中包含資料欄和分割區索引鍵的述詞,以確保查詢掃描的資料不會超過必要數目。

例如,假設上一個範例中的 sales 資料表也有 TIMESTAMP 資料類型的 sold_at 資料欄。如果您只想在特定時間範圍內獲得收入,則可以像這樣寫入查詢:

SELECT SUM(amount) AS total_revenue FROM sales WHERE sales_date = '2023-02-28' AND sold_at BETWEEN TIMESTAMP '2023-02-28 10:00:00' AND TIMESTAMP '2023-02-28 12:00:00' AND product_category = 'Toys'

如需有關查詢 Hive 和 Iceberg 資料之間的差異的詳細資訊,請參閱 如何寫入同樣按時間分割的時間戳記欄位的查詢

什麼是歸納?

歸納是一種將資料集的記錄整理至稱為儲存貯體的類別的方法。

儲存貯體歸納的含義與 Amazon S3 儲存貯體不同,且不應與 Amazon S3 儲存貯體混淆。在資料歸納中,具有相同屬性值的記錄會進入同一個儲存貯體。記錄會盡可能在儲存貯體之間平均分配,因此每個儲存貯體的資料量大致相同。

實際上,儲存貯體是檔案,而雜湊函數可確定記錄進入的儲存貯體。歸納的資料集在每個分割區的每個儲存貯體中會有一或多個檔案。檔案所屬的儲存貯體會以檔案名稱編碼。

歸納益處

當資料集依特定屬性進行歸納,而且您想要擷取該屬性具有特定值的記錄時,歸納功能非常有用。由於資料是歸納性質的,Athena 可以使用此值來判斷要查看的檔案。例如,假設資料集依 customer_id 進行歸納,而您想要尋找特定客戶的所有記錄。Athena 會判斷包含這些記錄的儲存貯體,而且只會讀取該儲存貯體中的檔案。

當您的資料欄具有高基數 (也就是,有許多不同的值)、平均分散,以及您經常查詢特定值的資料欄時,就會發生歸納的適當候選項。

注意

Athena 不支援使用 INSERT INTO 將新記錄新增至歸納的資料表。

支援依據已歸納資料欄進行篩選的資料類型

您可以在具有某些資料類型的歸納資料欄上新增篩選條件。Athena 支援對具有下列資料類型的已歸納資料欄進行篩選:

  • BOOLEAN

  • BYTE

  • DATE

  • DOUBLE

  • FLOAT

  • INT

  • LONG

  • SHORT

  • STRING

  • VARCHAR

Hive 和 Spark 支援

Athena 引擎版本 2 支援使用 Hive 儲存貯體演算法歸納的資料集,而 Athena 引擎版本 3 也支援 Apache Spark 歸納演算法。預設為 Hive 歸納。如果您的資料集是使用 Spark 演算法歸納,請使用 TBLPROPERTIES 子句將 bucketing_format 屬性值設定為 spark

注意

Athena 在每個 CREATE TABLE AS SELECT (CTAS) 查詢的分割區限制為 100 個。同樣地,您僅可以使用 INSERT INTO 陳述式將最多 100 個分割區新增至目的地資料表。100 個的限制只有在歸納和分割資料表時才會套用。

如果您超出此限制,您可能會收到錯誤訊息 HIVE_TOO_MANY_OPEN_PARTITIONS: Exceeded limit of 100 open writers for partitions/buckets (HIVE_TOO_MANY_OPEN_PARTITIONS:超過分割區/儲存貯體 100 個開啟寫入器的限制)。若要避開此限制,您可以使用 CTAS 陳述式和一系列的 INSERT INTO 陳述式,每個陳述式可建立或插入最多 100 個分割區。如需詳細資訊,請參閱 使用 CTAS 和 INSERT INTO 來解決 100 個分割區限制

歸納 CREATE TABLE 範例

若要為現有歸納的資料集建立資料表,請使用 CLUSTERED BY (column) 子句,後面接著 INTO N BUCKETS 子句。INTO N BUCKETS 子句指定了資料要歸納到的儲存貯體數量。

在下列 CREATE TABLE 範例中,使用 Spark 演算法,依 customer_idsales 資料集歸納成 8 個儲存貯體。CREATE TABLE 陳述式會使用 CLUSTERED BYTBLPROPERTIES 子句來設定相應的屬性。

CREATE EXTERNAL TABLE sales (...) ... CLUSTERED BY (`customer_id`) INTO 8 BUCKETS ... TBLPROPERTIES ( 'bucketing_format' = 'spark' )

歸納 CREATE TABLE AS (CTAS) 範例

若要使用 CREATE TABLE AS 指定歸納,請使用 bucketed_bybucket_count 參數,如下列範例所示。

CREATE TABLE sales WITH ( ... bucketed_by = ARRAY['customer_id'], bucket_count = 8 ) AS SELECT ...

歸納查詢範例

下列範例查詢會尋找特定客戶在一週內購買的產品名稱。

SELECT DISTINCT product_name FROM sales WHERE sales_date BETWEEN '2023-02-27' AND '2023-03-05' AND customer_id = 'c123'

如果此資料表依 sales_date 進行分割並依 customer_id 歸納,則 Athena 可以計算客戶記錄所在的儲存貯體。Athena 每個分割區最多只能讀取一個檔案。

其他資源