DynamoDBの並列Scan

前回の記事「 [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万件
| メモリ量 | セグメント数 | 処理時間 |
|---|---|---|
| 512MB | 2 | 15秒 |
| 3 | 14.4秒 | |
| 4 | 14.6秒 | |
| 5 | 14.4秒 | |
| 10 | 14.3秒 | |
| 2048MB | 2 | 4秒 |
| 3 | 4.3秒 | |
| 4 | 4.1秒 | |
| 5 | 4秒 | |
| 10 | 4.3秒 |
データ量: 10万件
| メモリ量 | セグメント数 | 処理時間 |
|---|---|---|
| 512MB | 2 | 49秒 |
| 3 | 49秒 | |
| 4 | 52.3秒 | |
| 5 | 53秒 | |
| 10 | 52秒 | |
| 2048MB | 2 | 13.1秒 |
| 3 | 14秒 | |
| 4 | 13.6秒 | |
| 5 | 14.6秒 | |
| 10 | 14.2秒 |
まとめ
パフォーマンス
- メモリ量の影響: メモリを2048MBに増加させると処理時間が大幅に短縮。
- セグメント数の影響: セグメント数の増加による処理時間の改善は限定的。
コストと効率
- 普通のScanと比較: メモリ量を増やした並列Scanの方が高速。ただし、メモリ量を増やす分、コストが増加する点には注意が必要です。
- 並列Queryと比較: パーティションキーを活用した並列Queryの方がさらに高速で効率的。並列Scanは特定のユースケース(例: パーティションキーが不明、全件取得が必要)で有効です。
結論
並列Scanは特定の状況で有効な手法ですが、パフォーマンス最適化を考えるなら、並列Queryの方がより効果的です。
次のような場合に並列Scanを検討してください:
- 全データをスキャンする必要がある。
- パーティションキーの設計が不十分でQueryが使えない。
効率的なDynamoDB運用の為には、データモデル設計を見直し、並列Queryを優先することをおすすめします!
この記事をシェアする
合同会社raisexでは一緒に働く仲間を募集中です。
ご興味のある方は以下の採用情報をご確認ください。