Vengo de una base de datos relacional y trato de trabajar con DynamoDB de Amazon.
Tengo una tabla con una clave hash "DataID" y un rango "CreatedAt" y un montón de elementos en él.
Estoy tratando de obtener todos los elementos que se crearon después de una fecha específica y se ordenaron por fecha. Lo cual es bastante sencillo en una base de datos relacional.
En DynamoDB, lo más cercano que pude encontrar es una consulta y el uso de la clave de rango mayor que el filtro. El único problema es que para realizar una consulta necesito una clave hash que anula el propósito.
Entonces, ¿qué estoy haciendo mal? ¿Está mal el esquema de mi tabla? ¿No debería ser única la clave hash? o hay otra forma de consultar?
fuente
CreatedAt
más de un cierto punto.Dada su estructura de tabla actual, esto no es posible actualmente en DynamoDB. El gran desafío es entender que la clave Hash de la tabla (partición) debe tratarse como si creara tablas separadas. De alguna manera, esto es realmente poderoso (piense en las claves de partición como la creación de una nueva tabla para cada usuario o cliente, etc.).
Las consultas solo se pueden realizar en una única partición. Ese es realmente el final de la historia. Esto significa que si desea consultar por fecha (querrá usar mseg desde época), entonces todos los elementos que desea recuperar en una sola consulta deben tener el mismo Hash (clave de partición).
Debo calificar esto. Puede hacerlo
scan
según el criterio que está buscando, eso no es un problema, pero eso significa que estará mirando cada fila de su tabla y luego verificando si esa fila tiene una fecha que coincida con sus parámetros. Esto es realmente caro, especialmente si, en primer lugar, está en el negocio de almacenar eventos por fecha (es decir, tiene muchas filas).Puede tener la tentación de poner todos los datos en una sola partición para resolver el problema, y absolutamente puede, sin embargo, su rendimiento será dolorosamente bajo, dado que cada partición solo recibe una fracción de la cantidad total establecida.
Lo mejor que puede hacer es determinar particiones más útiles para crear para guardar los datos:
¿Realmente necesita mirar todas las filas, o son solo las filas de un usuario específico?
¿Estaría bien reducir primero la lista por mes y hacer varias consultas (una para cada mes)? ¿O por año?
Si está haciendo un análisis de series de tiempo, hay un par de opciones, cambie la clave de partición a algo calculado
PUT
para hacerloquery
más fácil, o use otro producto de AWS como kinesis, que se presta al registro de solo anexos.fuente
yyyy
y un hash sobre eso, pero también cree unacreated
fecha que pueda usar como clave de rango. Luego, obtiene 10 GB de datos por año (27 MB por día), lo que probablemente esté bien para más circunstancias. Sin embargo, significa que debe crear una consulta por año cuando las consultas de fecha superan el límite del año, pero al menos funcionará y es más seguro que crear una clave hash ficticia.El enfoque que seguí para resolver este problema es crear un índice secundario global como se muestra a continuación. No estoy seguro de si este es el mejor enfoque, pero espero que sea útil para alguien.
Limitación impuesta al usuario de la API HTTP para especificar el número de días para recuperar datos, predeterminado a 24 horas.
De esta manera, siempre puedo especificar HashKey como el día de la fecha actual y RangeKey puede usar los operadores> y <mientras recupera. De esta forma, los datos también se distribuyen en varios fragmentos.
fuente
Su clave Hash (principal de tipo) tiene que ser única (a menos que tenga un rango como el indicado por otros).
En su caso, para consultar su tabla debe tener un índice secundario.
Su clave hash es ID Su índice secundario se define como: DataID-Created-index (ese es el nombre que usará DynamoDB)
Luego, puede realizar una consulta como esta:
Básicamente, su consulta se ve así:
El índice secundario aumentará las unidades de capacidad de lectura / escritura necesarias, por lo que debe tenerlo en cuenta. Todavía es mucho mejor que hacer un escaneo, que será costoso en lecturas y en tiempo (y creo que está limitado a 100 elementos).
Puede que esta no sea la mejor manera de hacerlo, pero para alguien acostumbrado a RD (también estoy acostumbrado a SQL) es la forma más rápida de ser productivo. Dado que no hay restricciones con respecto al esquema, puede preparar algo que funcione y una vez que tenga el ancho de banda para trabajar de la manera más eficiente, puede cambiar las cosas.
fuente
Puede hacer que la clave Hash sea algo similar a una identificación de 'categoría de producto', luego la clave de rango como una combinación de una marca de tiempo con una identificación única agregada al final. De esa manera, conoce la clave hash y aún puede consultar la fecha con mayor que.
fuente
Puede tener varias claves hash idénticas; pero solo si tiene una clave de rango que varía. Piense en ello como formatos de archivo; puede tener 2 archivos con el mismo nombre en la misma carpeta siempre que su formato sea diferente. Si su formato es el mismo, su nombre debe ser diferente. El mismo concepto se aplica a las claves hash / rango de DynamoDB; piense en el hash como el nombre y el rango como el formato.
Además, no recuerdo si los tenían en el momento del OP (no creo que los tuvieran), pero ahora ofrecen índices secundarios locales.
Según tengo entendido, ahora debería permitirle realizar las consultas deseadas sin tener que realizar un análisis completo. La desventaja es que estos índices deben especificarse en la creación de la tabla y también (creo) no pueden estar en blanco al crear un elemento. Además, requieren un rendimiento adicional (aunque normalmente no tanto como un escaneo) y almacenamiento, por lo que no es una solución perfecta, sino una alternativa viable para algunos.
Sin embargo, todavía recomiendo la respuesta de Mike Brant como el método preferido para usar DynamoDB; y usar ese método yo mismo. En mi caso, solo tengo una tabla central con solo una clave hash como mi ID, luego tablas secundarias que tienen un hash y un rango que se pueden consultar, luego el elemento apunta el código al "elemento de interés" de la tabla central, directamente .
Se pueden encontrar datos adicionales sobre los índices secundarios en la documentación de DynamoDB de Amazon aquí para aquellos interesados.
De todos modos, espero que esto ayude a cualquier otra persona que se encuentre en este hilo.
fuente
Respuesta actualizada No hay una forma conveniente de hacer esto usando Dynamo DB Queries con un rendimiento predecible. Una opción (subóptima) es utilizar un GSI con un HashKey & CreatedAt artificiales. Luego, consulte solo con HashKey y mencione ScanIndexForward para ordenar los resultados. Si puede encontrar una HashKey natural (digamos la categoría del artículo, etc.), este método es un ganador. Por otro lado, si mantiene el mismo HashKey para todos los elementos, afectará el rendimiento principalmente cuando su conjunto de datos supere los 10 GB (una partición)
Respuesta original: puede hacer esto ahora en DynamoDB mediante GSI. Cree el campo "CreatedAt" como GSI y emita consultas como (GT some_date). Almacene la fecha como un número (ms desde época) para este tipo de consultas.
Los detalles están disponibles aquí: Índices secundarios globales - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using
Esta es una característica muy poderosa. Tenga en cuenta que la consulta se limita a (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Condición - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
fuente
CreatedAt
debería ser la clave de rango de GSI, entonces deberá elegir una clave hash, y luego volverá a donde comenzó, porque podrá consultar GTCreatedAt
solo para un valor específico de la clave hash.