Avancé7 min de lecture

Parallel Scans DynamoDB

Un parallel scan découpe un Scan en N requêtes Scan indépendantes, chacune revendiquant un Segment du table, pour que plusieurs workers le lisent à la fois. C'est la seule façon qu'offre l'API Scan de lire tout un table plus vite que le throughput d'une partition ne le permet.

Qu'est-ce qu'un parallel scan DynamoDB ?

Un parallel scan DynamoDB découpe un Scan en N requêtes indépendantes, chacune revendiquant un Segment du table via Segment et TotalSegments, pour que plusieurs workers le lisent en concurrence. C'est la seule façon qu'offre l'API Scan de lire tout un table plus vite que le throughput d'une seule partition ne le permet — mais c'est encore une lecture complète, donc tu paies pour chaque item scanné.

  • Un Scan séquentiel lit une partition à la fois — sa vitesse est plafonnée au throughput d'une seule partition, peu importe la taille du table.
  • Segment + TotalSegments shardent la lecture entre TotalSegments workers ; chaque worker scanne sa propre tranche en parallèle.
  • DynamoDB hashe la pour assigner les segments, donc les tranches peuvent être déséquilibrées — plus de workers ne veut pas toujours dire plus vite.
  • C'est encore un Scan : tu paies pour lire chaque item, et un gros parallel scan peut drainer le throughput du table sous ton trafic live.

Pourquoi un Scan séquentiel est lent

Venant de SQL, une lecture full-table ressemble à une opération de streaming. Dans DynamoDB ce n'est pas le cas. Les données du table vivent à travers beaucoup de partitions physiques, mais un seul Scan les parcourt une à la fois, 1 MB par page.

Ça veut dire qu'un Scan plain ne peut jamais tirer que du budget de throughput d'une partition à un moment — même si le table est étalé sur des dizaines de partitions avec de la capacité idle. Plus le table est grand, plus ça rampe. (AWS : Parallel scan)

Découpe la lecture avec Segment et TotalSegments

Un parallel scan fixe le bottleneck. Tu choisis un nombre de workers, mets TotalSegments à ce nombre, et donnes à chaque worker un Segment distinct base zéro. Chaque worker lance son propre Scan ; DynamoDB les sert en concurrence.

Worker 0Scan  Segment=0  TotalSegments=4
Worker 1Scan  Segment=1  TotalSegments=4
Worker 2Scan  Segment=2  TotalSegments=4
Worker 3Scan  Segment=3  TotalSegments=4

Chaque worker page encore avec LastEvaluatedKey indépendamment — il possède son segment de la première page à la dernière. L'application recoud les quatre streams. Tu lis maintenant le throughput de quatre partitions à la fois au lieu d'une.

Exemple concret : l'export nocturne

Disons que tu gères un table de télémétrie, sensor-readings. Chaque item est une reading d'un device de terrain :

PK = "DEVICE#a83f"          (partition key — the device id)
SK = "TS#2026-06-22T03:14"  (sort key — ISO timestamp)
batteryMv  = 3120
tempC      = 41.8
firmwareTag = "fw-7.2.1"

Chaque nuit un cron dump tout le table vers S3 pour le warehouse analytics. Un Scan séquentiel de 80 GB prend des heures et entame à peine ta capacité de lecture provisionnée. Donc tu le fan-out entre huit workers :

Scan  sensor-readings  Segment=0  TotalSegments=8  ConsistentRead=falseScan  sensor-readings  Segment=7  TotalSegments=8  ConsistentRead=false

Huit workers, huit segments, une lecture de table environ huit fois plus rapide. Si tu n'as besoin que des readings récents, ajoute un FilterExpression pour écarter les anciens timestamps avant que les lignes touchent le wire — construis et inspecte cette expression dans l' Expression Builder :

FilterExpression:  begins_with(SK, :today)

Comment DynamoDB assigne les items aux segments

DynamoDB assigne chaque item à un segment en hashant sa partition key — pas par nombre de lignes, pas par nombre d'octets.

Donc chaque item partageant un PK atterrit dans le même segment. Dans sensor-readings, toutes les readings pour DEVICE#a83f vont à un worker, peu importe combien de timestamps ce device a ou combien sa est grande. (AWS : Parallel scan)

table sensor-readingshash partition keySegment 0DEVICE#a83fDEVICE#1c20Segment 1DEVICE#9be4Segment 2 (vide)

Les segments finissent inégaux. Un worker peut posséder trois devices bavards avec des millions de readings ; un autre peut tirer une tranche vide. Monter TotalSegments plus haut n'aidera pas si tes partition keys s'agglutinent — tu ajoutes juste des workers idle qui attendent le hot. Une distribution de clés uniforme est ce qui fait payer le fan-out.

Vois le coût de lecture avant de le lancer

Un parallel scan est un événement de throughput, pas un free lunch. La question honnête est « combien de ce table entier suis-je sur le point de lire ? » — et avant que DynoTable lance une lecture full-table, il te gate avec un dialog de confirmation montrant la taille approximative du table et le compte d'items plus un avertissement de capacité de lecture, puis streame la progression items-scannés live pendant que la lecture tourne, pour que le job nocturne ne te surprenne pas.

Pièges et quand ne pas s'embêter

  • La falaise de throughput. Un scan à haut TotalSegments peut consommer toute la capacité de lecture du table en secondes, affamant le trafic live. Sur un table qui sert des utilisateurs, throttle chaque worker avec le paramètre Limit ou scanne hors pic. (AWS : Parallel scan)
  • C'est encore le mauvais outil pour un modèle d'accès. Les parallel scans sont pour des jobs full-table délibérés — exports, backfills, migrations. Si tu tends la main vers un pour répondre à une query récurrente, c'est un signal de modeling : ajoute un GSI et fais-en un Query à la place.
  • SELECT * en PartiQL est le même scan déguisé. Il compile en un Scan séquentiel. Quand tu as vraiment besoin d'analytics cross-item — un GROUP BY, un JOIN, un agrégat — le SQL Workbench de DynoTable les exécute côté client sur un result set borné, au lieu de marteler le table.
  • La strong consistency double la facture. Un Scan default vers des lectures . Pour un export, laisse ConsistentRead=false sauf si chaque page doit refléter les toutes dernières écritures — et note même qu'un scan strongly consistent s'étale sur des minutes, donc ce n'est pas un snapshot point-in-time (utilise PITR/Export pour ça).

Étapes suivantes

Modélise tes clés pour que les lectures du quotidien n'aient jamais besoin d'un scan — commence par single-table design et Query vs Scan. Quand un job full-table est vraiment le bon appel, essaie DynoTable pour lancer des lectures full-table avec un avertissement taille-et-coût d'emblée et une progression de scan live.

Mis à jour