Utilizzo dello sharding di scrittura negli indici secondari globali per query di tabelle selettive in DynamoDB - Amazon DynamoDB

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Utilizzo dello sharding di scrittura negli indici secondari globali per query di tabelle selettive in DynamoDB

Quando è necessario eseguire query su dati recenti entro una finestra temporale specifica, il requisito di DynamoDB di fornire una chiave di partizione per la maggior parte delle operazioni di lettura può rappresentare una sfida. Per risolvere questo scenario, è possibile implementare un modello di query efficace utilizzando una combinazione di sharding di scrittura e un indice secondario globale (GSI).

Questo approccio consente di recuperare e analizzare in modo efficiente i dati sensibili al fattore tempo senza eseguire scansioni complete delle tabelle, che possono richiedere molte risorse e costi. Progettando strategicamente la struttura e l’indicizzazione delle tabelle è possibile creare una soluzione flessibile che supporti il recupero dei dati basato sul tempo, mantenendo al contempo prestazioni ottimali.

Progettazione dei modelli

Durante il lavoro con DynamoDB, è possibile superare le sfide derivanti dal recupero dei dati basato sul tempo implementando un modello sofisticato che combina lo sharding di scrittura e gli indici secondari globali per consentire query flessibili ed efficienti su finestre di dati recenti.

Struttura della tabella
  • Chiave di partizione (PK): “Username”

Struttura del GSI
  • Chiave di partizione GSI (PK_GSI): "#» ShardNumber

  • Chiave di ordinamento del GSI (SK_GSI): ISO 8601 timestamp (ad esempio, “2030-04-01T12:00:00Z”)

Progettazioni di modelli per dati di serie temporali.

Strategia di sharding

Supponendo che si decida di utilizzare 10 shard, i numeri degli shard potrebbero variare da 0 a 9. Quando si registrano i log di un’attività, è necessario calcolare il numero di shard (ad esempio, utilizzando una funzione hash sull’ID utente e quindi prendendo il modulo del numero di shard) e anteponendolo alla chiave di partizione del GSI. Questo metodo distribuisce le voci su diversi shard, mitigando il rischio di partizioni calde.

Esecuzione di query sul GSI sottoposto a sharding

L’esecuzione di query su tutti gli shard per gli elementi all’interno di un determinato intervallo di tempo in una tabella DynamoDB, in cui i dati sono sottoposti a sharding su più chiavi di partizione, richiede un approccio diverso rispetto all’esecuzione di query su una singola partizione. Poiché le query DynamoDB sono limitate a una singola chiave di partizione alla volta, non è possibile eseguire query direttamente su più shard con una singola operazione di query. Tuttavia, è possibile ottenere il risultato desiderato tramite la logica a livello di applicazione eseguendo più query, ciascuna mirata a uno shard specifico, e quindi aggregando i risultati. Di seguito viene descritto come procedere.

Come eseguire query sugli shard e aggregarli
  1. Identifica l’intervallo di numeri di shard utilizzati nella strategia di sharding. Ad esempio, con 10 frammenti, i numeri degli shard andrebbero da 0 a 9.

  2. Per ogni shard, costruisci ed esegui una query per recuperare gli elementi entro l’intervallo di tempo desiderato. Queste query possono essere eseguite in parallelo per migliorare l’efficienza. Usa la chiave di partizione con il numero di shard e la chiave di ordinamento con l’intervallo di tempo per queste query. Ecco un esempio di query per un singolo shard:

    aws dynamodb query \ --table-name "YourTableName" \ --index-name "YourIndexName" \ --key-condition-expression "PK_GSI = :pk_val AND SK_GSI BETWEEN :start_date AND :end_date" \ --expression-attribute-values '{ ":pk_val": {"S": "ShardNumber#0"}, ":start_date": {"S": "2024-04-01"}, ":end_date": {"S": "2024-04-30"} }'
    Esempio di query per un singolo shard.

    Dovreste replicare questa query per ogni shard, regolando la chiave di partizione di conseguenza (ad esempio, "ShardNumber#1 «," ShardNumber #2 «,...," #9 «). ShardNumber

  3. Aggrega i risultati di ogni query dopo che tutte le query sono state completate. Esegui questa aggregazione nel codice dell’applicazione, combinando i risultati in un unico set di dati che rappresenta gli elementi di tutti gli shard entro l’intervallo di tempo specificato.

Considerazioni sull’esecuzione di query parallele

Ogni query consuma la capacità di lettura della tabella o dell’indice. In caso di utilizzo di un throughput allocato, assicurati che la tabella disponga di una capacità sufficiente per gestire l’espansione di query parallele. In caso di utilizzo di capacità on demand, tieni presente le potenziali implicazioni in termini di costi.

esempio di codice

Per eseguire query parallele su shard in DynamoDB usando Python, è possibile usare la libreria boto3, che è l’SDK Amazon Web Services per Python. Questo esempio presuppone che boto3 sia installato e configurato con le credenziali appropriate. AWS

Il seguente codice Python dimostra come eseguire query parallele su più shard per un determinato intervallo di tempo. Vengono utilizzati oggetti futuri simultanei per eseguire query in parallelo, riducendo il tempo di esecuzione complessivo rispetto all’esecuzione sequenziale.

import boto3 from concurrent.futures import ThreadPoolExecutor, as_completed # Initialize a DynamoDB client dynamodb = boto3.client('dynamodb') # Define your table name and the total number of shards table_name = 'YourTableName' total_shards = 10 # Example: 10 shards numbered 0 to 9 time_start = "2030-03-15T09:00:00Z" time_end = "2030-03-15T10:00:00Z" def query_shard(shard_number): """ Query items in a specific shard for the given time range. """ response = dynamodb.query( TableName=table_name, IndexName='YourGSIName', # Replace with your GSI name KeyConditionExpression="PK_GSI = :pk_val AND SK_GSI BETWEEN :date_start AND :date_end", ExpressionAttributeValues={ ":pk_val": {"S": f"ShardNumber#{shard_number}"}, ":date_start": {"S": time_start}, ":date_end": {"S": time_end}, } ) return response['Items'] # Use ThreadPoolExecutor to query across shards in parallel with ThreadPoolExecutor(max_workers=total_shards) as executor: # Submit a future for each shard query futures = {executor.submit(query_shard, shard_number): shard_number for shard_number in range(total_shards)} # Collect and aggregate results from all shards all_items = [] for future in as_completed(futures): shard_number = futures[future] try: shard_items = future.result() all_items.extend(shard_items) print(f"Shard {shard_number} returned {len(shard_items)} items") except Exception as exc: print(f"Shard {shard_number} generated an exception: {exc}") # Process the aggregated results (e.g., sorting, filtering) as needed # For example, simply printing the count of all retrieved items print(f"Total items retrieved from all shards: {len(all_items)}")

Prima di eseguire questo codice, assicurati di sostituire YourTableName e YourGSIName con la tabella e i nomi dei GSI effettivi della configurazione di DynamoDB. Inoltre, regola le variabili total_shards, time_start e time_end in base alle esigenze specifiche.

Questo script esegue query su ogni shard alla ricerca di elementi entro l’intervallo di tempo specificato e aggrega i risultati.