Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

#deswebIO - NoSQL

No description
by

Álvaro Everlet

on 18 February 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of #deswebIO - NoSQL

alvaroeverlet - @aeverlet - feb 2013 #deswebIO - NoSQL Presentación +12 años de experiencia en desarrollo

Ahora estoy en:
helloworldsolutions (fundador)
carriots (CTO) - carriots.com ¿Porqué plantearse usar NoSQL? ¿Porqué estoy aquí? Vengo del mundo del desarrollo web y de aplicaciones empresariales

He entrado recientemente en el mundo del NoSQL

Contaré mi experiencia Alvaro Everlet
@aeverlet CARRIOTS: un proyecto de envergadura con:

Muchos datos, pero muchos de verdad
Encima todos con una estructura variable
Necesidad de escalar
Debe estar en la nube
Alta disponibilidad
"Write intensive" ¿No valdría una BD de las de siempre? Es cierto que la dominación de las BBDD relacionales (RDBMS) es absoluta

Sabemos hacer queries complejas, índices, replicación master-slave...

Las relaciones entre tablas y la normalización de los datos nos acompañan desde que hacemos las cosas "bien" Pero las cosas tienden a complicarse Hasta que lo vemos unos meses más tarde con intención de depurar una parte del proceso.... y piensas que la siguiente será de otra forma Se nos ocurren ideas complejas que resuelven los problemas de una forma "elegante"

Patrón EAV - Entity Atribute Value usado por Magento Un nuevo concursante: NoSQL En realidad no es tan nuevo: Carlo Strozzi "NoSQL" 1998

Las implementaciones reales son de este siglo, y responden a las necesidades actuales de los entornos web masivos:

Datos masivos
Entornos en la nube montados en clusters
Datos sin estructura definida
Los ORM no siempre son la mejor opción Alternativas NoSQL Ahora que me interesa la alternativa NoSQL toca escoger BBDD Clave valor
BBDD documentales
BBDD column family
BBDD de grafo Clave valor Una clave enlaza con un valor

Un valor es típicamente un conjunto de datos (un registro)
Pero puede variar en función de la BD y ser una lista, un array asociativo, una cadena de caracteres, etc.

Hay implementaciones "in memory" muy rápidas pero menos fiables Clave valor Uso:
Sesiones
Perfil de usuario, preferencias
Shopping carts Evitar su uso:
Cuando se necesitan relaciones
Transacciones multioperación
Queries sobre datos (no sobre las claves) Productos en el mercado:
Redis (VMWare)
Voldemort
Riak
Memcached Documentales BD = schema
Tabla = Colección
Fila = Documento
Columna = ??

Uso:
Logs
CMS, blogs, etc.
Analítica en tiempo real
Ecommerce Evitar su uso:
Transacciones multioperación

Productos en el mercado
MongoDB (10gen)
CouchDB (Apache)
RavenDB Column family BD = keyspace
Tabla = conjunto de columnas (column family)
Fila = Fila
Columna (fija) = Columna (variable)

Uso:
Logs
CMS, blogs, etc.
Contadores
Datos con caducidad Evitar su uso:
Prototipos o proyectos sin queries definidas

Productos en el mercado:
Apache Cassandra
Amazon Dynamo DB
HBase
Hypertable
Google Bigdata BBDD de grafo BD de nodos con relaciones.
Las relaciones pueden tener atributos.
La idea es persistir un dato e interpretarlo de forma diferente en función de sus relaciones.
Twitter: followers y follows

Uso:
Datos relacionados
Logísitca, routing, etc.
Motor de recomendaciones

Evitar su uso:
Cuando no son necesarios los nodos relacionados
Actualizaciones en cascada
Aplicaciones que requieren operar con el grafo completo Productos en el mercado:
FlockDB (Twitter)
HyperGraphDB
Infinite Graph
OrientDB NoSQL no vale para todo Establece que se deben escoger 2 de entre:
Consistency (Consistencia)
Availability (Disponibilidad)
Partition tolerance (Tolerancia a la separación) Teorema CAP (Brewer) Cuando NO usar NoSQL
(recomendación) Transacciones multioperación
Un sistema relacional “heredado”
Pocos datos
Validaciones fuertes sobre los tipos de datos La mejor opción Polyglot persistence (M. Fowler) Un mecanismo de persistencia por caso

En el caso de Carriots:
Datos -> MongoDB
Transacciones -> PostgreSQL
Sesiones -> Redis
Logs -> MongoDB Entrando al mundo NoSQL ¿Porqué MongoDB? Necesitábamos una BD documental
Cubre los requisitos de NoSQL que buscamos
Pensado para el escalado
Gran comunidad MongoDB Base de datos documental Una fila es un documento JSON
Un tabla es una colección: contiene documentos

Un documento puede ser:
{
“nombre”: “Alvaro Everlet”,
“evento”: “#deswebIO”
} Schemaless
Consultas con aggregate y map reduce
Indexación
Replicación
Particionado y balanceo con sharding
Javascript en servidor Schemaless No hay estructura definida db.coches.save({
"marca": "Audi",
"modelo": "A4",
"matricula": "8823 AAA",
"extras":["lunas tintadas","sport kit"]
}); db.coches.find();

db.coches.find({"marca":"BMW"});
db.coches.find({"extras":"sport kit"}); db.coches.save({
"marca": "BMW",
"modelo": "320",
"matricula": "1234 AAA"
}); Schemaless db.coches.save({
"marca": "Volkswagen",
"modelo": "Golf",
"matricula": "8745 BBB",
"conductor": {
"nombre":"Alvaro",
"dni":"123456789"}
}); db.coches.save({
"marca": "Citroën",
"modelo": "C4",
"matricula": "4567 CCC",
"conductor": {
"nombre":"Miguel",
"dni":"987654321"}
}); db.coches.find({"conductor.nombre":"Alvaro"});
db.coches.find({"conductor":{$exists:1}}); ¿Cómo diseño la base de datos? Sin esquema... eso será el desmadre ¿no? Opciones:
Embed: Integrar un documento dentro de otro
Link: Indicar la clave de otro documento

¿Cuál usar en cada caso?
En función de cómo se usan los datos. Relación uno a uno Ejemplo: persona - curriculum Persona:
{
"_id" : 100,
"nombre" : "Alvaro"
}

Curriculum:
{
"_id" : 200,
"formacion" : ["colegio tal","universidad pascual"],
"puestos" : ["puesto1","puesto2"]
} Relación uno a uno Linking Persona:
{
"_id":100,
"nombre":"Alvaro",
"cv":200
}

Curriculum:
{
"_id":200,
"formacion":["colegio tal","universidad pascual"],
"puestos":["puesto1","puesto2"],
"persona":100
} Relación uno a uno Embedding Persona:
{
"_id":100,
"nombre":"Alvaro",
"cv":{
"formacion":["colegio tal","universidad pascual"],
"puestos":["puesto1","puesto2"] }
} Relación uno a uno Embedding 2 Curriculum:
{
"_id":200,
"formacion":["colegio tal","universidad pascual"],
"puestos":["puesto1","puesto2"],
"persona":{
"nombre":"Alvaro"
}
} Relación uno a muchos Ejemplo: persona - ciudad Ciudad:
{
"_id":100,
"nombre":"Madrid",
"posicion":["40°25′08″N","3°41′31″O"],
"cp":28
} Persona:
{
"_id":200,
"nombre":"Alvaro"
}
{
"_id":230,
"nombre":"Miguel"
} Relación uno a muchos Linking Ciudad:
{
"_id":100,
"nombre":"Madrid",
"posicion":["40°25′08″N","3°41′31″O"],
"cp":28,
"personas":[200,230]
} Persona:
{
"_id":200,
"nombre":"Alvaro",
"ciudad":100
}
{
"_id":230,
"nombre":"Miguel",
"ciudad":100
} Relación uno a muchos Embedding 1 Persona:
{
"_id":200,
"nombre":"Alvaro",
"ciudad":{
"nombre":"Madrid",
"posicion":["40°25′08″N","3°41′31″O"],
"cp":28
}
} {
"_id":230,
"nombre":"Miguel",
"ciudad":{
"nombre":"Madrid",
"posicion":["40°25′08″N","3°41′31″O"],
"cp":28
}
} Relación uno a muchos Embedding 2 Ciudad:
{
"_id":100,
"nombre":"Madrid",
"posicion":["40°2508N","3°4131O"],
"cp":28,
"personas":[{"nombre":"Alvaro"},{"nombre":"Miguel"}]
} Relación muchos a muchos Ejemplo: libros - autores Libros:
{
"_id":100,
"titulo":"MongoDB for beginners",
"ISBN": "12-3456789-01"
}
{
"_id":101,
"titulo":"Advanced Javascript",
"ISBN": "91-3433789-46"
} Autores:
{
"_id":200,
"nombre":"Alvaro"
}
{
"_id":230,
"nombre":"Miguel"
}
{
"_id":240,
"nombre":"Daniel"
} Relación muchos a muchos Linking Libros:
{
"_id":100,
"titulo":"MongoDB for beginners",
"ISBN": "12-3456789-01"
"autores":[200,240]
}
{
"_id":101,
"titulo":"Advanced Javascript",
"ISBN": "91-3433789-46"
"autores":[230]
} Autores:
{
"_id":200,
"nombre":"Alvaro"
"libros":[100,120]
}
{
"_id":230,
"nombre":"Miguel"
"libros":[101,130,160]
}
{
"_id":240,
"nombre":"Daniel"
"libros":[100]
} NoSQL vs. SQL SELECT *
FROM users

db.users.find()

SELECT id, user_id, status
FROM users

db.users.find(
{ },
{ user_id: 1, status: 1 }
) SELECT user_id, status
FROM users

db.users.find(
{ },
{ user_id: 1, status: 1, _id: 0 }
)


SELECT *
FROM users
WHERE status = "A"

db.users.find(
{ status: "A" }
) NoSQL vs. SQL SELECT user_id, status
FROM users
WHERE status = "A"

db.users.find(
{ status: "A" },
{ user_id: 1, status: 1, _id: 0 }
) SELECT *
FROM users
WHERE status = "A"
AND age = 50

db.users.find(
{ status: "A",
age: 50 }
) SELECT *
FROM users
WHERE status = "A"
OR age = 50

db.users.find(
{ $or: [ { status: "A" } ,
{ age: 50 } ] }
) SELECT *
FROM users
WHERE user_id like "%bc%"

db.users.find(
{ user_id: /bc/ }
) NoSQL vs. SQL SELECT COUNT(*)
FROM users

db.users.count()

SELECT *
FROM users
WHERE status = "A"
ORDER BY user_id DESC

db.users.find( { status: "A" } ).sort( { user_id: -1 } ) UPDATE users
SET status = "C"
WHERE age > 25

db.users.update(
{ age: { $gt: 25 } },
{ $set: { status: "C" } },
{ multi: true }
) Agregación Dos aproximaciones:

Map-reduce
Aggregation framework Agregación - Map reduce Map: de un conjunto de datos de la BD extrae una lista de pares clave-valor

Reduce: toma pares clave-valor y une los pares con la misma clave Agregación - Map reduce {
_id:100,
pedido:[
{art:"pera",cant:2,precio:0.5,total:1},
{art:"manzana",cant:10,precio:0.3,total:3},
{art:"kiwi",cant:5,precio:0.5,total:2.5}
]
}
{
_id:101,
pedido:[
{art:"pera",cant:4,precio:0.5,total:2},
{art:"platano",cant:7,precio:0.4,total:2.8},
{art:"mango",cant:1,precio:1.5,total:1.5}
]
} {
_id:101,
pedido:[
{art:"manzana",cant:4,precio:0.3,total:1.2},
{art:"platano",cant:3,precio:0.4,total:1.2},
{art:"pera",cant:2,precio:0.5,total:1}
]
} Agregación - Map reduce {"pera":{cant:2,total:1}}
{"manzana":{cant:10,total:3}}
{"kiwi":{cant:5,total:2.5}}

{"pera":{cant:4,total:1.2}}
{"platano":{cant:7,total:2.8}}
{"mango":{cant:1,total:1.5}}

{"manzana":{cant:4,total:1.2}}
{"platano":{cant:3,total:1.2}}
{"pera":{cant:2,total:1}} Map: conjunto de clave-valor Agregación - Map reduce Reduce: juntando claves {"pera":{cant:8,total:3.2}}

{"manzana":{cant:14,total:4.2}}

{"kiwi":{cant:5,total:2.5}}

{"platano":{cant:10,total:4}}

{"mango":{cant:1,total:1.5}} Agregación - Aggregation framework Es la cobertura de las funcionalidades del group by de SQL.

Lo mejor es verlo con ejemplos.

Los documentos de la colección son así:

{
cust_id: "abc123",
ord_date: ISODate("2012-11-02T17:04:11.102Z"),
status: 'A',
price: 50,
items: [ { sku: "xxx", qty: 25, price: 1 },
{ sku: "yyy", qty: 25, price: 1 } ]
} Agregación - Aggregation framework SELECT SUM(price) AS total
FROM orders

db.orders.aggregate( [
{ $group: { _id: null,
total: { $sum: "$price" } } }
] )
Suma el campo precio de los pedidos

SELECT cust_id,
SUM(price) AS total
FROM orders
GROUP BY cust_id

db.orders.aggregate( [
{ $group: { _id: "$cust_id",
total: { $sum: "$price" } } }
] )
Suma los precios de cada cust_id SELECT cust_id,
SUM(price) AS total
FROM orders
GROUP BY cust_id
ORDER BY total

db.orders.aggregate( [
{ $group: { _id: "$cust_id",
total: { $sum: "$price" } } },
{ $sort: { total: 1 } }
] )

Suma los precios de cada cust_id y ordena por el resultado de la suma. Indices Mejora del rendimiento de las queries
Se trata de evitar un “Collection scan”
Misma estrategia que en otras BBDD
Se usa una estructura en árbol (Btree)
Permite indices compuestos

Uso de comandos “explain” para saber lo que hace Mongo Indices db.coches.ensureIndex({"marca":1});
db.coches.find().explain();
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 5,
"nscannedObjects" : 5,
"nscanned" : 5,
"nscannedObjectsAllPlans" : 5,
"nscannedAllPlans" : 5,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {

},
"server" : "MBAA.local:27017"
} Indices db.coches.find({"marca":"BMW"}).explain();
{
"cursor" : "BtreeCursor marca_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"marca" : [
[
"BMW",
"BMW"
]
]
},
"server" : "MBAA.local:27017"
} Corriendo sobre un cluster Sacarle partido a un cluster mediante:
Replicación
Partición de los datos Corriendo sobre un cluster Se copia la base de datos en otros nodos del cluster
Cada nodo es una copia de otro, tiene los mismos datos

Uno es maestro, se encarga de las escrituras
El resto son eslavos, toman los datos del maestro
Si el maestro cae los esclavos eligen un nuevo maestro
Cuando el maestro vuelve pasa a ser un esclavo más

Ofrece seguridad y posibilidad de balancear la carga de lectura Replicación - Replica set Corriendo sobre un cluster Partición - Sharding El DBA selecciona una clave y reparte los datos entre los nodos en función de la clave (shard key).

Por ejemplo: código postal, país, etc.

Cada nodo tiene un conjunto de datos diferente.

Se balancea la lectura y la escritura. Corriendo sobre un cluster Solución ideal Lo ideal es combinar Replica Set y Sharding y tener datos separados y que entre sí estén replicados Conclusiones NoSQL no es un tipo de base de datos es sencillamente no relacional
NoSQL es buena opción en función de las necesidades
NoSQL no es una opción como en el caso de entornos transaccionales multioperación

MongoDB es una alternativa de mercado válida para entornos web de producción
MongoDB dispone de las herramientas para cubrir el salto desde las BBDD relacionales Referencias NoSQL Distilled - Sadalage & Fowler - Addison Wesley 2013
Towards Robust Distributed Systems - Brewer - PODC keynote 2000
MongoDB official site: docs.mongodb.org
M101: MongoDB for developers - 10gen education - education.10gen.com
M102: MongoDB for DBAs - 10gen education - education.10gen.com
MongoDB: The Definitive Guide - Chodorow & Dirolf - O’Reilly 2010 ¡Gracias! Alvaro Everlet
@aeverlet #deswebIO - NoSQL
feb 2013 Samuel
David
Mendoza Pablo
Jorge
Javier helloworldsolutions team
Full transcript