掃描 DynamoDB 中的資料表 - Amazon DynamoDB

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

掃描 DynamoDB 中的資料表

Amazon DynamoDB 中的 Scan 操作會讀取資料表或次要索引中的每個項目。根據預設,Scan 操作會傳回資料表或索引中每個項目的所有資料屬性。您可以使用 ProjectionExpression 參數,以便 Scan 只傳回部分屬性,而不會全部傳回。

Scan 一律會傳回結果集。如果找不到相符項目,表示結果集是空的。

單一 Scan 請求最多可擷取 1 MB 的資料。或者,DynamoDB 可將篩選條件表達式套用至此資料,縮減結果後再傳回給使用者。

掃描的篩選條件表達式

若您需要更精確的 Scan 結果,您可以選擇性的提供篩選條件表達式。篩選條件表達式會判斷要傳回 Scan 結果中的哪些項目。所有其他結果皆會捨棄。

篩選條件表達式會在 Scan 完成後、結果傳回前套用。因此,無論是否有篩選條件表達式,Scan 都會使用相同數量的讀取容量。

Scan 操作最多可擷取 1 MB 的資料。系統會先套用這項限制,再評估篩選條件表達式。

使用 Scan,您可在篩選條件表達式中指定任何屬性,包括分割區索引鍵和排序索引鍵屬性。

篩選條件表達式的語法和條件表達式的語法相同。篩選條件表達式可以使用與條件表達式相同的比較子、函數和邏輯運算子。如需邏輯運算子的詳細資訊,請參閱 DynamoDB 中的條件和篩選條件表達式、運算子和函數

範例

下列 AWS Command Line Interface (AWS CLI) 範例會掃描Thread資料表,並僅傳回特定使用者上次發佈到 的項目。

aws dynamodb scan \ --table-name Thread \ --filter-expression "LastPostedBy = :name" \ --expression-attribute-values '{":name":{"S":"User A"}}'

限制結果集的項目數

Scan 操作可讓您限制在結果中傳回的項目數目。若要執行此作業,請將 Limit 參數設定為您希望 Scan 操作在篩選表達式評估前回傳的最大項目數。

例如,假設您 Scan 一份資料表,將 Limit 值設為 6 且不使用篩選條件表達式。此 Scan 結果會包含資料表中的前六個項目。

現在假設您在 Scan 中新增一個篩選條件表達式。在本案例中,DynamoDB 會將篩選條件表達式套用至傳回的六個項目,捨棄那些不符的項目。最終的 Scan 結果會包含 6 個或以下項目,視篩選的項目數而定。

為結果編製分頁

DynamoDB 會對 Scan 操作的結果進行分頁。透過編製分頁,Scan 結果會分成數個大小為 1 MB (或更小) 的資料「頁」。應用程式可以處理結果的第一頁、第二頁,以此類推。

單一 Scan 只會傳回符合 1 MB 大小限制的結果集。

為判斷是否有更多結果,並且一次擷取一頁結果,應用程式應執行下列作業:

  1. 檢查低層級 Scan 結果:

    • 若結果包含 LastEvaluatedKey 元素,請接著進行步驟 2。

    • 若結果中沒有 LastEvaluatedKey,就表示再也沒有要擷取的項目。

  2. 建構新的 Scan 請求,和前一個請求使用相同的參數。但這一次採用步驟 1 的 LastEvaluatedKey 值,並用它做為新 Scan 要求的 ExclusiveStartKey 參數。

  3. 執行新的 Scan 請求。

  4. 前往步驟 1。

換句話說,LastEvaluatedKey 回應的 Scan 應做為下一個 ExclusiveStartKey 請求的 Scan 使用。若 Scan 回應中沒有 LastEvaluatedKey 元素,表示您已擷取到結果的最終頁。(檢查是否沒有 LastEvaluatedKey 是確定您是否已到達結果集末頁的唯一方式)。

您可以使用 AWS CLI 來檢視此行為。會重複 AWS CLI 將低階Scan請求傳送至 DynamoDB ,直到結果LastEvaluatedKey中不再出現 為止。請考慮下列 AWS CLI 範例,掃描整個Movies資料表,但只會傳回特定類型的影片。

aws dynamodb scan \ --table-name Movies \ --projection-expression "title" \ --filter-expression 'contains(info.genres,:gen)' \ --expression-attribute-values '{":gen":{"S":"Sci-Fi"}}' \ --page-size 100 \ --debug

通常, 會自動 AWS CLI 處理分頁。不過,在此範例中, AWS CLI --page-size 參數會限制每頁的項目數量。--debug 參數會列印請求及回應的下層資訊。

注意

您的分頁結果也會根據您傳遞的輸入參數而有所不同。

  • 使用 aws dynamodb scan --table-name Prices --max-items 1 會傳回 NextToken

  • 使用 aws dynamodb scan --table-name Prices --limit 1 會傳回 LastEvaluatedKey

另請注意,使用特定的 --starting-token 需要 NextToken 值。

如果您執行此範例,DynamoDB 的第一個回應會類似以下內容。

2017-07-07 12:19:14,389 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":7,"Items":[{"title":{"S":"Monster on the Campus"}},{"title":{"S":"+1"}}, {"title":{"S":"100 Degrees Below Zero"}},{"title":{"S":"About Time"}},{"title":{"S":"After Earth"}}, {"title":{"S":"Age of Dinosaurs"}},{"title":{"S":"Cloudy with a Chance of Meatballs 2"}}], "LastEvaluatedKey":{"year":{"N":"2013"},"title":{"S":"Curse of Chucky"}},"ScannedCount":100}'

回應中的 LastEvaluatedKey 會指出並未擷取所有項目。 AWS CLI 然後, 會向 DynamoDB 發出另一個Scan請求。此請求和回應模式會持續到最終回應出現為止。

2017-07-07 12:19:17,830 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":1,"Items":[{"title":{"S":"WarGames"}}],"ScannedCount":6}'

若沒有 LastEvaluatedKey,就表示已不再有要擷取的項目。

注意

會 AWS SDKs處理低階 DynamoDB 回應 (包括是否存在 LastEvaluatedKey),並提供各種摘要來引導Scan結果。例如,SDK適用於 Java 的文件界面提供支援,java.util.Iterator以便您一次可以逐一瀏覽結果。

如需各種程式設計語言的程式碼範例,請參閱 Amazon DynamoDB 入門指南和您的語言 AWS SDK文件。

計算結果中的項目

除了符合您條件的項目之外,Scan 回應還包含了下列元素:

  • ScannedCount:在套用任何 ScanFilter 前評估的項目數。ScannedCount 值很高,但 Count 結果很少或沒有,表示 Scan 操作不足。如未在請求中使用篩選條件,則 ScannedCountCount 相同。

  • Count:套用篩選條件表達式 (若有的話) 之後剩下的項目數。

注意

若不使用篩選條件表達式,則 ScannedCountCount 會有相同的值。

Scan 結果集的大小大於 1 MB,則 ScannedCountCount 僅代表總項目的部分計數。您需要執行多項 Scan 操作,才能擷取所有的結果 (請參閱為結果編製分頁)。

每個 Scan 回應都包含經該特定 Scan 請求處理過的項目 ScannedCountCount。若要取得所有 Scan 請求的總計,您可以為 ScannedCountCount 記錄流水帳。

掃描使用的容量單位

您可以 Scan 任何資料表或次要索引。Scan 操作會使用讀取容量單位,如下所示。

若您對下列進行 Scan DynamoDB 使用的讀取容量單位就會來自...
資料表 該資料表的佈建讀取容量。
全域次要索引 該索引的佈建讀取容量。
本機次要索引 該基礎資料表的佈建讀取容量。

根據預設,Scan 操作不會傳回任何使用之讀取容量的相關資料。但您可以在 ReturnConsumedCapacity 請求中指定 Scan 參數,來取得這項資訊。下列為 ReturnConsumedCapacity 的有效設定:

  • NONE:不會傳回耗用的容量資料。(此為預設值)。

  • TOTAL:回應包括耗用的讀取容量單位總數。

  • INDEXES:回應顯示耗用的讀取容量單位總數,以及每個資料表和存取之索引的耗用容量。

DynamoDB 會根據項目數量和這些項目的大小來計算使用的讀取容量單位數量,而不是根據傳回應用程式的資料量。因此,無論您請求所有屬性 (預設行為) 或只請求部分屬性 (使用投影表達式),使用的容量單位數都相同。無論您是否使用篩選條件表達式,此數字也相同。 Scan會耗用最低讀取容量單位,以每秒執行一個強烈一致性的讀取,或對於最多 4 KB 的項目,每秒執行兩個最終一致性的讀取。如果您需要讀取大於 4KB 的項目,DynamoDB 需要額外的讀取請求單位。空的資料表和具有少量分割區金鑰的非常大的資料表可能會看到超出掃描資料量的部分額外RCUs收費。這涵蓋了處理Scan請求的成本,即使沒有資料。

掃描的讀取一致性

根據預設,Scan 操作會執行最終一致讀取。這表示 Scan 的結果可能不會反映最近完成之 PutItemUpdateItem 操作所造成的變更。如需詳細資訊,請參閱 DynamoDB 讀取一致性

若您要進行強烈一致讀取,請在 Scan 開始時,將 ConsistentRead 請求中的 true 參數設為 Scan。這可確保 Scan 開始前即已完成的所有寫入操作,都會包含在 Scan 回應中。

ConsistentRead 設為 true,再結合 DynamoDB Streams,在資料表備份或複寫案例中很實用。首先使用 ConsistentRead 設為 true 的 Scan,取得和資料表資料一致的副本。在 Scan 期間,DynamoDB Streams 會紀錄資料表發生的所有額外寫入活動。Scan 完成後,您可將串流的寫入活動套用至資料表。

注意

與將 ConsistentRead 保留預設值 (false) 相較,將 ConsistentRead 設成 trueScan 操作會使用兩倍的讀取容量單位。

平行掃描

根據預設,Scan 操作會依序處理資料。Amazon DynamoDB 會以 1 MB 的增量將資料傳回應用程式,而應用程式會執行額外的 Scan 操作來擷取下一個 1 MB 的資料。

掃描的資料表或索引越大,Scan 完成所需的時間就更多。此外,循序 Scan 可能並不總是能夠完全使用佈建的讀取輸送容量:即使 DynamoDB 將大型資料表的資料分配到多個實體分割區,Scan 操作一次只能讀取一個分割區。因此,Scan 的輸送量受到單一分割區的最大輸送量限制。

若要解決這些問題,Scan 操作在邏輯上可能會將資料表或次要索引分為多個區段,其中有多個應用程式工作者平行掃描區段。每個工作者都可以是執行緒 (在支援多執行緒的程式設計語言中) 或作業系統程序。若要執行平行掃描,每個工作者都會使用下列參數發出自己的 Scan 請求:

  • Segment:特定工作者要掃描的區段。每個工作者應該使用不同的 Segment 值。

  • TotalSegments:平行掃描區段的總數。此值必須與應用程式要使用的工作者數目相同。

下圖顯示多執行緒應用程式如何以三度平行處理執行平行 Scan

多執行緒應用程式,透過將資料表分割為三個區段來執行平行掃描。

在此圖中,應用程式產生三個執行緒,並為每個執行緒指派一個數字。(區段從零開始,所以第一個數字永遠為 0。) 每個執行緒都會發出 Scan 請求、將 Segment 設定為指定號碼,並將 TotalSegments 設定為 3。每個執行緒都會掃描其指定的區段,一次擷取 1 MB 的資料,並將資料傳回至應用程式的主執行緒。

SegmentTotalSegments 的值會套用至個別 Scan 請求,並且您可以隨時使用不同的值。您可能需要對這些值以及使用的工作者數量進行試驗,直到應用程式達到最佳效能為止。

注意

具有大量工作者的平行掃描可以輕易耗用所掃描資料表或索引的所有佈建輸送量。如果資料表或索引也會造成來自其他應用程式的大量讀取或寫入活動,就最好避免這類掃描。

若要控制每個請求傳回的資料量,請使用 Limit 參數。這有助於預防某個工作者耗用所有佈建輸送量的情況,避免犧牲所有其他工作者。