amazon web services - consistent - ¿Cómo consultar DynamoDB por fecha(clave de rango), sin una clave hash obvia?
consistent read dynamodb (3)
Aunque un Global Secondary Index
parece ajustarse a sus requisitos, cualquier intento de incluir información relacionada con la timestamp
como parte de su Hash Key
probablemente creará lo que se conoce como "partición en caliente", lo que es extremadamente indeseable.
El acceso desigual ocurrirá ya que los elementos más recientes se recuperarán con mucha más frecuencia que los antiguos. Esto no solo afectará su rendimiento sino que también hará que su solución sea menos rentable.
Vea algunos detalles de la documentación:
Por ejemplo, si una tabla tiene un número muy pequeño de valores de clave de partición de gran acceso, posiblemente incluso un solo valor de clave de partición muy usado, el tráfico de solicitudes se concentra en un pequeño número de particiones, posiblemente solo una partición. Si la carga de trabajo está muy desequilibrada, lo que significa que se enfoca de manera desproporcionada en una o unas pocas particiones, las solicitudes no alcanzarán el nivel de rendimiento general aprovisionado. Para obtener el máximo rendimiento de DynamoDB, cree tablas en las que la clave de partición tenga un gran número de valores distintos, y los valores se soliciten de manera bastante uniforme, de la forma más aleatoria posible.
De acuerdo con lo que se indica, el id
parece ser una buena opción para su Hash Key
(también conocida como Partition Key
), no cambiaría eso ya que las claves GSI funcionan de la misma manera en lo que se refiere a la partición. Como nota aparte, el rendimiento está altamente optimizado cuando recupera sus datos al proporcionar la Primary Key
completa, por lo que debemos tratar de encontrar una solución que proporcione eso siempre que sea posible.
Yo sugeriría crear tablas separadas para almacenar las claves primarias según la fecha en que se actualizaron. Puede segmentar los datos en tablas según la granularidad que mejor se adapte a sus casos de uso. Por ejemplo, digamos que desea segmentar las actualizaciones por día:
a. Sus actualizaciones diarias se podrían almacenar en tablas con la siguiente convención de denominación: updates_DDMM
segundo. Las tablas updates_DDMM
solo tendrían los id
(claves hash de la otra tabla)
Ahora diga que la última fecha de actualización de la aplicación fue de hace 2 días (04/07/16) y que necesita obtener los registros recientes, entonces necesitará:
yo. Escanee las tablas updates_0504
y updates_0604
para obtener todas las claves hash.
ii. Finalmente, obtenga los registros de la tabla principal (que contiene lat / lng, nombre, etc.) enviando un BatchGetItem
con todas las claves hash obtenidas.
BatchGetItem
es súper rápido y hará el trabajo como ninguna otra operación.
Se puede argumentar que la creación de tablas adicionales agregará costos a su solución general ... bueno, con GSI
básicamente está duplicando su tabla (en caso de que esté proyectando todos los campos) y agregando ese costo adicional para todos los registros de ~ 2k, siendo estos recientemente actualizado o no ...
Parece contra intuitivo crear tablas como esta, pero en realidad es una buena práctica cuando se trata de datos de series de tiempo (de la documentación de AWS DynamoDB):
[...] las aplicaciones pueden mostrar un patrón de acceso desigual en todos los elementos de la tabla donde los últimos datos del cliente son más relevantes y su aplicación puede acceder a los últimos elementos con mayor frecuencia y, a medida que pasa el tiempo, se accede menos a estos elementos. los artículos son raramente accedidos. Si este es un patrón de acceso conocido, podría tenerlo en cuenta al diseñar el esquema de su tabla. En lugar de almacenar todos los elementos en una sola tabla, puede usar varias tablas para almacenar estos elementos. Por ejemplo, podría crear tablas para almacenar datos mensuales o semanales. Para la tabla que almacena los datos del último mes o semana, donde la tasa de acceso a los datos es alta, solicita un rendimiento más alto y para las tablas que almacenan datos más antiguos, puedes reducir el rendimiento y ahorrar en recursos.
Puede ahorrar en recursos almacenando artículos "calientes" en una tabla con una configuración de rendimiento más alta, y elementos "fríos" en otra tabla con una configuración de rendimiento más baja. Puede eliminar elementos antiguos simplemente eliminando las tablas. Opcionalmente, puede hacer una copia de seguridad de estas tablas en otras opciones de almacenamiento, como Amazon Simple Storage Service (Amazon S3). Eliminar una tabla completa es significativamente más eficiente que eliminar elementos uno por uno, lo que esencialmente duplica el rendimiento de escritura al igual que tantas operaciones de eliminación como operaciones de colocación.
Fuente: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html
Espero que eso ayude. Saludos.
Necesito mantener los datos locales en una aplicación de iOS sincronizada con los datos en una tabla de DynamoDB. La tabla de DynamoDB es ~ 2K filas, con solo una clave de hash ( id
), y los siguientes atributos:
-
id
(uuid) -
lastModifiedAt
(timestamp) -
name
-
latitude
-
longitude
Actualmente estoy escaneando y filtrando por lastModifiedAt
, donde lastModifiedAt
es mayor que la última fecha de actualización de la aplicación, pero me imagino que será caro.
La mejor answer que puedo encontrar es agregar un Índice Secundario Global con lastModifiedAt
como el rango, pero no hay una clave de hash obvia para el GSI.
¿Cuál es la mejor práctica cuando se necesita consultar por rango usando un GSI, pero no hay una clave de hash obvia? Alternativamente, si la única opción es un escaneo completo, ¿existen prácticas recomendadas para reducir el costo?
Podría usar la parte "día" de la marca de tiempo como hash y utilizar la marca de tiempo completa como rango.
Si bien la respuesta de D.Shawley me ayudó a orientarme en la dirección correcta, faltaron dos consideraciones para un GSI:
- El rango de hash + debe ser único, pero la indicación de fecha y hora (su enfoque recomendado) no es necesariamente única.
- Al usar solo el día como hash, necesitaría un gran número de consultas para obtener los resultados de cada día desde la última fecha de actualización (que podría ser hace meses o años).
Como tal, aquí está el enfoque que tomé:
- Creó un índice secundario global (GSI) con la clave hash como
YearMonth
(por ejemplo,201508
) y el rango comoid
- Consulte el GSI varias veces, una consulta por cada mes desde la última fecha de actualización. Las consultas también se filtran con
lastModifiedAt > [given timestamp]
.