¿Lee la tienda todos los pedidos?
Una tienda en línea guarda un millón de pedidos. Una clienta quiere ver los suyos. ¿Lee la tienda el millón entero para encontrarlos?
Una buena tabla de DynamoDB no lo hace. Una consulta va directa a los pedidos de ella y no lee nada más. Esta lección explica por qué una consulta cuesta menos que un escaneo y cómo leer los contadores que devuelve el servicio.
Al final de esta lección
Nota
Puedo explicar por qué una consulta cuesta menos que un escaneo.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Clave de partición | el atributo que decide dónde se guarda un elemento | |
| Clave de ordenación | el atributo que ordena los elementos de una misma clave de partición | |
| Condición de clave | la prueba que hace una consulta sobre las claves | |
| Consulta | una lectura que va a una sola clave de partición | query |
| Escaneo | una lectura que mira todos los elementos de la tabla | scan |
| Filtro | una prueba que se aplica después de leer los elementos |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Dos claves dan una dirección a cada elemento
Nuestra tabla de pedidos tiene dos atributos clave. La clave de partición es client. Decide dónde guarda el servicio un elemento, así que todos los pedidos de una clienta quedan juntos.
La clave de ordenación es order_id. Ordena los pedidos de una misma clienta. Las dos claves juntas nombran un solo elemento. Dos pedidos pueden compartir clienta, pero nunca las dos claves.
Ejemplo resuelto: cómo se colocan los pedidos
| Clave de partición: client | Clave de ordenación: order_id | Otros atributos |
|---|---|---|
| lucia | 1 | té, pagado, total 4 |
| lucia | 2 | leche, nuevo, total 2 |
| lucia | 3 | tarta, pagado, total 15 |
| pablo | 7 | té, pagado, total 8 |
| marta | 4 | leche, nuevo, total 6 |
| marta | 9 | té, pagado, total 3 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Consulta a un sitio, escaneo a todos
Una consulta nombra la clave de partición. Tiene que hacerlo, o el servicio la rechaza con una ValidationException y el estado HTTP 400. El servicio va directo a esa clienta y lee solo esos pedidos.
Un escaneo no nombra nada. Lee todos los elementos de la tabla, uno tras otro. Las dos respuestas llevan un Count, los elementos devueltos, y un ScannedCount, los elementos mirados.
Pruébalo: una consulta y un escaneo
orders = [
{"client": {"S": "lucia"}, "order_id": {"N": "1"}, "status": {"S": "pagado"}},
{"client": {"S": "lucia"}, "order_id": {"N": "2"}, "status": {"S": "nuevo"}},
{"client": {"S": "lucia"}, "order_id": {"N": "3"}, "status": {"S": "pagado"}},
{"client": {"S": "pablo"}, "order_id": {"N": "7"}, "status": {"S": "pagado"}},
{"client": {"S": "marta"}, "order_id": {"N": "4"}, "status": {"S": "nuevo"}},
{"client": {"S": "marta"}, "order_id": {"N": "9"}, "status": {"S": "pagado"}},
]
def scan(items):
return {"Count": len(items), "ScannedCount": len(items)}
def query(items, client):
found = []
for item in items:
if item["client"]["S"] == client:
found.append(item)
return {"Count": len(found), "ScannedCount": len(found)}
print("escaneo:", scan(orders))
print("consulta lucia:", query(orders, "lucia"))
# Cambia "lucia" por "pablo". ¿Cuántos elementos mira ahora la consulta?
Un filtro recorta la respuesta, no el trabajo
Una condición de clave también puede probar la clave de ordenación. Por ejemplo, un order_id de 2 o más. Entonces el servicio lee solo esa parte de la partición.
Un filtro prueba cualquier otro atributo, como status. Se aplica después de leer los elementos, así que cambia el Count pero no el ScannedCount.
Ejemplo resuelto: pagados de lucia desde el 2
| Paso | Elementos que quedan | Qué pasó |
|---|---|---|
| La clave de partición es lucia | 3 | los pedidos 1, 2 y 3 |
| Clave de ordenación 2 o más | 2 | los pedidos 2 y 3, así que ScannedCount es 2 |
| Filtro: status es pagado | 1 | solo el pedido 3, así que Count es 1 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que un filtro abarata la lectura. No lo hace. El servicio lee primero los elementos y descarta algunos después. Pon en la condición de clave todo lo que puedas, y usa un filtro solo para lo que sobre.
Pruébalo: lee los dos contadores
answer = {
"Count": 1,
"ScannedCount": 2,
"Items": [
{"client": {"S": "lucia"}, "order_id": {"N": "3"}, "status": {"S": "pagado"}},
],
}
dropped = answer["ScannedCount"] - answer["Count"]
print("mirados:", answer["ScannedCount"])
print("devueltos:", answer["Count"])
print("descartados por el filtro:", dropped)
# Cambia ScannedCount a 3. ¿Cuántos dice ahora que descartó el filtro?