DynamoDBの並列Scan

投稿更新日: 2025/6/5

サムネイル

前回の記事「 [DynamoDBからの全データ取得におけるプラクティス]https://blog.raisex.jp/articles/o0cmjsrwp73fm9jd2i3s0d80) 」では、パーティション分散と並列Queryを活用した全データ取得の効果を検証しました。

今回の記事では、もう一つの手法である並列Scanについて取り上げ、どのような効果が得られるのかを実験します。


並列Scanとは?

並列Scanは、DynamoDBのパーティション分散を利用し、データのスキャン処理を複数のセグメント(Segment)に分割して並列で実行する方法です。

通常のScan操作は1つのプロセスで順次処理を行うため、データ量が増えるほど時間がかかります。

一方、並列Scanでは複数のワーカーを用いて並列処理を行うため、大量データのスキャンを効率化できます。

基本動作

  • Segment: データを分割する単位。
  • TotalSegments: 全体の分割数。
  • 各ワーカーが指定されたSegmentを担当し、全体のデータセットを並列に処理します。

実験内容

以下の条件で並列Scanを実施し、処理時間を測定しました。

  • データ量: 3万件、10万件
  • メモリ量: 512MB、2048MB
  • セグメント数: 2, 3, 4, 5, 10

ソースコード

以下は実験に使用したAWS Lambda用のPythonコードです。

import boto3
import os
from concurrent.futures import ThreadPoolExecutor

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test_datas')

# 最大ワーカー数
max_workers = min(32, os.cpu_count() * 5)

def parallel_scan(segment, total_segments):
    print(f'segment = {segment}, total_segments = {total_segments}')
    items = []
    options = {
        'Segment': segment,
        'TotalSegments': total_segments
    }
    done = False

    while True:
        response = table.scan(**options)
        next_token = response.get('LastEvaluatedKey', None)
        items.extend(response['Items'])
        if next_token:
            options['ExclusiveStartKey'] = next_token
        else:
            break
    return items

def lambda_handler(event, context):
    total_segments = 2  # 並列度を調整

    # ThreadPoolExecutorを使用して並列スキャンを実行
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [executor.submit(parallel_scan, segment, total_segments) for segment in range(total_segments)]
        results = []
        for future in futures:
            results.extend(future.result())

        print(f'{len(results)}件')
    return {
        'StatusCode': 200
    }

実験結果

データ量: 3万件

メモリ量セグメント数処理時間
512MB215秒
314.4秒
414.6秒
514.4秒
1014.3秒
2048MB24秒
34.3秒
44.1秒
54秒
104.3秒

データ量: 10万件

メモリ量セグメント数処理時間
512MB249秒
349秒
452.3秒
553秒
1052秒
2048MB213.1秒
314秒
413.6秒
514.6秒
1014.2秒

まとめ

パフォーマンス

  • メモリ量の影響: メモリを2048MBに増加させると処理時間が大幅に短縮。
  • セグメント数の影響: セグメント数の増加による処理時間の改善は限定的。

コストと効率

  • 普通のScanと比較: メモリ量を増やした並列Scanの方が高速。ただし、メモリ量を増やす分、コストが増加する点には注意が必要です。
  • 並列Queryと比較: パーティションキーを活用した並列Queryの方がさらに高速で効率的。並列Scanは特定のユースケース(例: パーティションキーが不明、全件取得が必要)で有効です。

結論

並列Scanは特定の状況で有効な手法ですが、パフォーマンス最適化を考えるなら、並列Queryの方がより効果的です。

次のような場合に並列Scanを検討してください:

  • 全データをスキャンする必要がある。
  • パーティションキーの設計が不十分でQueryが使えない。

効率的なDynamoDB運用の為には、データモデル設計を見直し、並列Queryを優先することをおすすめします!


この記事をシェアする

合同会社raisexでは一緒に働く仲間を募集中です。

ご興味のある方は以下の採用情報をご確認ください。