Cuando necesita consultar datos recientes en un intervalo de tiempo específico, el requisito de DynamoDB de proporcionar una clave de partición para la mayoría de las operaciones de lectura puede suponer un reto. Para abordar este escenario, puede implementar un patrón de consulta eficaz mediante una combinación de partición de escritura y un índice secundario global (GSI).
Este enfoque le permite recuperar y analizar de manera eficiente datos confidenciales sin realizar análisis completos de tablas, que pueden requerir muchos recursos y ser costosos. Mediante el diseño estratégico de la estructura e indexación de la tabla, puede crear una solución flexible que admita la recuperación de datos basada en el tiempo, al mismo tiempo que mantiene un rendimiento óptimo.
Temas
Diseño de patrón
Cuando trabaje con DynamoDB, puede superar los desafíos de recuperación de datos basados en el tiempo mediante la implementación de un patrón sofisticado que combina particiones de escritura e índices secundarios globales para habilitar consultas flexibles y eficientes en ventanas de datos recientes.
Estructura de la tabla
Clave de partición (PK): “Username”
Estructura del GSI
Clave de partición de GSI (PK_GSI): “ShardNumber#”
Clave de clasificación de GSI (SK_GSI): marca temporal ISO 8601 (por ejemplo, “2030-04-01T12:00:00Z”)

Estrategia de particiones
Suponiendo que decida utilizar diez particiones, los números de partición podrían estar en un intervalo del cero al nueve. Al registrar una actividad, debe calcular el número de partición (por ejemplo, mediante una función de hash en el ID de usuario y, a continuación, tomando el módulo del número de particiones) y anteponerlo a la clave de partición de GSI. Este método distribuye las entradas entre diferentes particiones, lo que mitiga el riesgo de particiones activas.
Consulta del GSI particionado
La consulta en todos los fragmentos de elementos en un intervalo de tiempo concreto en una tabla de DynamoDB, donde los datos se fragmentan en varias claves de partición, requiere un enfoque diferente al de la consulta en una sola partición. Como las consultas de DynamoDB están limitadas a una sola clave de partición a la vez, no puede consultar directamente varias particiones con una sola operación de consulta. No obstante, puede lograr el resultado deseado mediante la lógica en el nivel de aplicación; para ello, realice varias consultas, cada una de ellas dirigida a una partición específica y, a continuación, agregue los resultados. En el siguiente procedimiento se explica cómo hacerlo.
Consulta y agregación de particiones
Identifique el intervalo de números de particiones utilizado en la estrategia de partición. Por ejemplo, si tiene diez particiones, los números de partición estarán en el intervalo del cero al nueve.
Para cada partición, construya y ejecute una consulta para recuperar elementos en el intervalo de tiempo deseado. Estas consultas pueden ejecutarse en paralelo para mejorar la eficiencia. Utilice la clave de partición con el número de partición y la clave de clasificación con el intervalo de tiempo para estas consultas. Aquí tiene un ejemplo de consulta para una sola partición:
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"} }'
Debería replicar esta consulta para cada partición, ajustando la clave de partición en consecuencia (por ejemplo, “ShardNumber#1”, “ShardNumber#2”, ..., “ShardNumber#9”).
Agregue los resultados de cada consulta una vez que todas las consultas estén completas. Realice esta agregación en el código de la aplicación; para ello, combine los resultados en un único conjunto de datos que represente los elementos de todas las particiones en el intervalo de tiempo especificado.
Consideraciones sobre la ejecución de consultas paralelas
Cada consulta consume capacidad de lectura de la tabla o el índice. Si utiliza rendimiento aprovisionado, asegúrese de que la tabla esté aprovisionada con capacidad suficiente para manejar la ampliación de consultas paralelas. Si utiliza la capacidad bajo demanda, tenga en cuenta las posibles implicaciones de costos.
Ejemplo de código
Para ejecutar consultas paralelas en particiones de DynamoDB con Python, puede utilizar la biblioteca boto3, que es el SDK de Amazon Web Services para Python. En este ejemplo se supone que tiene boto3 instalado y configurado con las credenciales de AWS adecuadas.
En el siguiente código Python se muestra cómo realizar consultas paralelas en varias particiones para un intervalo de tiempo determinado. Utiliza futuros concurrentes para ejecutar consultas en paralelo, lo que reduce el tiempo total de ejecución en comparación con la ejecución secuencial.
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)}")
Antes de ejecutar este código, asegúrese de reemplazar YourTableName
y YourGSIName
por los nombres reales de la tabla y GSI de la configuración de DynamoDB. Además, ajuste las variables total_shards
, time_start
y time_end
de acuerdo con los requisitos específicos de su empresa.
Este script consulta cada partición en busca de elementos en el intervalo de tiempo especificado y agrega los resultados.