Dentro del Bid Data tenemos diferentes procesos y herramientas para majenar cada uno de ellos:
| Proceso | Herramienta |
|---|---|
| Almacenamiento | HDFS |
| Procesamiento | Spark, MapReduce (Java), HIVE (SQL) |
HIVE es una herramienta que con conocimientos de SQL permite procesar, a traves de MapReduce, los datos almacenados.
Con un sistema distribuido logramos que muchos ordenadores trabajen de forma conjunta y saquen informacion y presentarla de forma casi inmediata.
El maestro es el que sabe en que esclavo se encuentra cada fichero. Este maestro debe ser el sistema mas potente.
Una herramienta que se encarga de esto es HDFS. La version 2 de HDFS perimte tener un maestro clon.
Replicacion: un bloque de un fichero repartido en multiples nodos.
Al ejecutar una llamada al fichero, lo que hace el maestro es enviar ese codigo a cada nodo y la respuesta de cada uno es lo que el maestro manda como respuesta a la llamada.
Es la capacidad que tiene un sistema para crecer sin afectar el rendimiento. La escalabilidad horizontal es ingresar mas nodos. Con eso se consigue mas capacidad de almacenamiento. Cuando esto pasa, los nodos ya existentes pasan informacion a los nuevos para nivelar el almacenamiento en todos.
Se pierde consistencia pero se esta en muchos nodos.
Poder conseguir que la informacion se vea al momento. Para que todos lo vean al mismo tiempo, una posibilidad es tenerlo todo en un nodo, el problema es que si se cae, se arruina para todos. Cargar la red supone que todos los nodos esten disponibles. Se pierde disponibilidad.
Puede dividir las tareas y que se ejecuten al mismo tiempo.
En estas bases de datos no se manejan relaciones. El lenguaje de cada base de datos es diferente. En el lenguaje SQL existe un problema de distribucion de los datos, ya que una BD relacional no puede ser distribuida y si se necesita mas espacio no queda mas opcion que hacer un escalado vertical, que es mas caro.
Las alternativas que han salido para el SQL, como sistemas NoSQL pueden destacarse Big Table de Google. Estas alternativas nacieron por la necesidad de ejecutarse en un cluster. En las BD NoSQL es incompatible las transacciones ACID, entonces se hace commit a nivel de agregado. Esto permite tambien que sea mas rapido.
Ningun sistema puede ser 100%
Un registro es la clave y a partir de eso se saca el resto.
Los formatos que mas se utilizan son JSON y SSON
Los conjuntos de datos relacionados son tratados como una unidad. Son autoindexables.
Es el identificador. Siempre debe haber uno. Si no se asigna, BSON lo genera automaticamente y tiene el formato:
12 bytes -> 24 digitos hexadecimales + Timestamp + Id del ordenador + Codigo de proceso + Contador incremental
Nos conviene tener un identificador generado por nosotros cuando queremos crear una relacion, es decir, si queremos poner ese mismo objeto, con otra decripcion, en otra coleccion (como el DNI de un alumno y los trabajos que ha hecho).
Es la unidad basica de datos. Contiene pares clave-valor (registros de SQL).
Los documentos se almacenan en colecciones (tablas de SQL).
Mongo cuando un documento es insertado, guarda un poco mas de espacio del que realmente ocupa. Al actualizar, intenta utilizar el espacio guardado de mas y si no, saca el documento anterior y se lo lleva mas abajo. Esto penaliza mucho al rendimiento. Si mucho se va a actualizar, MongoDB no se debe utilizar.
| Codigo | Descripcion |
|---|---|
mongoimport --host localhost --db curso --collection lecturer --type json --file "c:\cargas\2.Introduccion\datos_lecturer.json" |
Insertar documentos en una coleccion. Funciona solo fuera de MongoDB |
db.estudiantes.insertOne( { nombre: 'Diego', edad: 26 } ) |
Importar un documento a la coleccion |
db.estudiantes.insertMany( [ { nombre: 'Tania', edad: 35 }, { nombre: 'Jorge', edad: 18 } ] ) |
Insertar dos o mas documentos con dos o mas campos a la coleccion estudiantes. Este insert se puede escribir sin el Many |
db.estudiantes.insert ( { _id : 1, nombre: 'Ana', edad: 55 } ) |
Insertar un documento a la coleccion con numero de id propio |
db.estudiantes.insertOne ( { nombre: 'Edgar', edad: 15, accesos: { usuario: 'EdgarRo', password: 'CriCri19_112' } } ) |
Insertar un documento con array |
load ("c:/cargas/3.1.OperacionesLectura/3.1.FiltrarDocumentos/cargaPuntuaciones1.js") |
carga un archivo desde dentro de MongoDB |
| Codigo | Descripcion |
|---|---|
db.estudiantes.update( { nombre: 'Tania' }, { $set: { edad: 30 } } ) |
Actualizar campos en el documento. Si no se pone el signo $, se hace un reemplazo de todos los campos del documento y solo deja el campo que hemos cambiado. Es decir, en el ejemplo quitara el nombre y dejara como campo unico la edad |
db.estudiantes.deleteOne( { nombre: 'Diego' } ) |
Elimina el documento con el que haga match el nombre |
| Codigo | Descripcion |
|---|---|
| db | Ver que base de datos esta activa |
| show dbs | Mostar la base de datos |
| use |
Cambiar de base de datos |
| show collections | Muestra las colecciones de la bd |
db.coleccion.find(criterio,proyeccion)
| Codigo | Descripcion |
|---|---|
db.lecturer.find().pretty() |
Muestra todos los documentos de la coleccion de forma ordenada. Los muestra de 20 en 20. Este es el simil de SELECT * FROM lecturer en SQL |
db.coleccion.find( {criterio1: 'Criteria'}, {_id: 0o1, proyeccion2: 1o0)} ).pretty |
Encontrar un dato filtrando por un campo. El campo ‘criterio’ es por lo que se quiere filtrar. El campo ‘proyeccion’ con las columnas que se muestran en el resultado. Si no se escribe nada, muestra todos los campos. Si se pone al menos un campo, el id siempre lo muestra a menos que se indique con un 0 o un 1. Ejemplo: db.lecturer.find( {a:45}, {_id:1, a:1, d:1} ).pretty(). Este es el simil de SELECT id, proyeccion2 FROM coleccion WHERE status = "Criteria" de SQL |
db.coleccion.find( {criterio1: '_'}, {criterio2: '_'} ).pretty |
Encontrar un dato filtrando por mas de un campo. |
db.coleccion.findOne() |
Muestra un documento de la coleccion |
db.lecturer.find().count() |
Muestra el numero de documentos de la coleccion |
db.estudiantes.find( { "accesos.usuario": 'EdgarRo' } ) |
Busca criterios dentro de un array de un documento. En el ejemplo, busca los usuarios EdgarRo en el array accesos |
{ <field1>: <value1>, ... } Ej.{ idCliente: 4 } |
Filtro find para Mongo Compass |
Operadores disponibles: $eq, $gt, $gte, $lt, $lte, $ne, $or, $and, $not, $nor
Una lista completa puede encontrarse aqui:https://docs.mongodb.com/manual/reference/operator/query/#query-selectors
| Codigo | Descripcion |
|---|---|
db.lecturer.find( {a: {$gt 40}}, {_id:1, a:1, d:1} ).pretty() |
Muestra los campos id, a y d en los documentos que a sea mayor que 40, de la coleccion de lecturer |
db.lecturer.find({$and: [ {a: {$gt:45}}, {a: {$lt:50}} ]}).pretty().count() |
Muestra cuantos documentos hay que cumplan que a sea mayor que 45 y menos que 50, de la coleccion de lecturer. Si no tiene el count devuelve los documentos. puede tambien construirse sin el and: db.inventory.find( { price: { $ne: 1.99, $exists: true } } ) |
db.lecturer.find({$or: [ {a: {$gt:20}}, {a: {$lt:40}} ]}).pretty() |
Muestra muestra los campos que cumplan que a sea mayor que 45 o menores que 40, de la coleccion de lecturer |
db.puntuaciones.find( { $or : [ { $and : [ { tipo : 'ejercicio' }, { puntuacion : {$lt: 50} } ] }, { $and : [ { tipo : 'pregunta' }, { puntuacion : {$gt: 70} } ] } ] } ) |
Selecciones AND y OR con multiples expresiones especificando el mismo operador |
db.puntuaciones2.find ({"puntuaciones.examen" : {$gt:70}}) |
Seleccionar campos dentro de un array que cumplan con una condicion |
Una vision mejor del ultimo codigo se observa aqui:
Operadores disponibles: $all, $size, $in, $nin
Una lista completa puede encontrarse aqui:https://docs.mongodb.com/manual/reference/operator/query/#query-selectors
| Codigo | Descripcion |
|---|---|
db.gimnasio.find( { idCliente : {$in : [4 , 30]} } ) |
Muestra los documentos en los que el idCliente sea 4 o 30. Por que no se usa $or? Se usa $in en lugar de $or cuando realizamos selecciones con el mismo ccampo |
db.gimnasio.find( { idCliente: {$nin: [ 3 , 4 ]} }) ) |
Selecciona todos los documentos de la coleccion que no tengan como idCliente los numero 3 y 4 |
db.gimnasio.find( { preferencias: { $all: [ 'Padel', 'Tenis' ]} } ) |
Selecciona los documentos en los que las preferencias son Tenis o Padel. $all es equivalente a $and y dan el mismo resultado |
db.gimnasio.find( { preferencias: { $size: 2 } } ) |
Selecciona los documentos que tengan el numero de elementos especificados en $size. En el ejemplo, selecciona los documentos que tienen solo 2 preferencias |
{ idCliente : {$in : [4 , 30]} } |
Sintaxis de seleccion para MongoDB Compass |
db.gimnasio.find( { $and: [ { preferencias : { $all : [ 'Natación' , 'Padel' ] } }, { preferencias : { $size : 2 } } ] } ) |
Selecciona los documentos en los que las preferencias sean solo Natacion y Padel. Para segurarse que el documento no incluye ninguna otra preferencia se utiliza el $size |
db.puntuaciones3.find ( { puntuaciones: { $elemMatch : { tipo:"examen", puntuacion: {$gt:99} } } } ) |
Selecciona los documentos dentro de documentos, que cumplen la condicion dada. el $elemMatch es importante para que la consulta entienda que debe (en este ejemplo) tomar el tipo: 'examen' y la puntuacion: {$gt: 99} de ese campo tipo en especifico |
Esto es util para trabajar con una coleccion y agregar o quitar documentos sin alterar la coleccion de la base de datos.
| Codigo | Descripcion |
|---|---|
var doc = db.gimnasio.findOne() |
Crea la variable doc y le asigna un documento aleatorio de la coleccion gimnasio. Para revisar la variable se escribe el nombre de la misma en la linea de comando y muestra un documento (ej. { “_id" : ObjectId(“5318bed1d2550240c5629b4f”), “idCliente” : 4, “fechaAlta” : ISODate(“2014-03-06T18:30:41.277Z”),preferencias" : [“Padel”, “Natación”, “Elíptica”, “Padel”, “Tenis” ] } ) |
doc.b = 1 |
Crea un nuevo campo ‘b’ en la variable doc. Este nuevo campo no se encuentra en la base de datos, solo en la variable creada |
db.coleccion.save (doc) |
Guarda el documento de la variable en la coleccion. Si le paso un documento que ya tiene id, reemplazará el documento |
delete doc._id, delete doc.preferencias |
Elimina un campo del documento. Si hago db.coleccion.save (doc) para guardar la variable con el campo ’_id’ eliminado, se mantiene el documento original y se guarda uno nuevo con un nuevo id |
Es importante porque las colecciones no tienen una estructura especifica. Por eso se hacen consultas por todos los documentos que tienen un campo determinado.
Se utiliza en el proceso de almacenamiento y procesamiento. Mueve el codigo que ejecutamos al nodo donde se ha almacenado la informacion. Hadoop no permite modificaciones de ficheros
Es la forma en como Hadoop gestiona la fase de almacenamiento.
| Concepto | Descripcion |
|---|---|
| Maestro | Namenode |
| Esclavos | Datanodes |
| Bloques | HDFS genera distintos bloques a partir de un fichero. Estos ficheros particionados son de 128MBs cada unoFactor de Factor de replicacion |
| Maestro secundario | Secondary Namenode. Se levanta de forma manual cuando al primario le sucede algo. Zookeper lo puede hacer automatico. Este secundario esta e StandBy y se encarga de funciones de mantenimiento. Este maestro lo que hace es leer cada cierto tiempo (hora) lo que tenga edits y actualiza el archivo fsimage y luego le devuelve esto al Namenode.Cada vez que se pasa la info al fsimage el edits se renombra |
| Deamons | Procesos que se estan ejecutando |
La instalacion puede seguirse con estas paginas: https://www.edureka.co/blog/install-hadoop-single-node-hadoop-cluster https://www.youtube.com/watch?v=l1QmEPEAems
Al editar el .bashrc, se debe ingresar esta informacion:
# Set HAdoop-related enviroment variables export HADOOP_HOME=/home/vargasde1/hadoop-3.1.2 export HADOOP_CONF_DIR=/home/vargasde1/hadoop-3.1.2/etc/hadoop export HADOOP_MAPRED_HOME=/home/vargasde1/hadoop-3.1.2 export HADOOP_COMMON_HOME=/home/vargasde1/hadoop-3.1.2 export HADOOP_HDFS_HOME=/home/vargasde1/hadoop-3.1.2 export YARN_HOME=/home/vargasde1/hadoop-3.1.2 export PATH=$PATH:/home/vargasde1/hadoop-3.1.2/bin export HDFS_NAMENODE_USER="root" export HDFS_DATANODE_USER="root" export HDFS_SECONDARYNAMENODE_USER="root" export YARN_RESOURCEMANAGER_USER="root" export YARN_NODEMANAGER_USER="root"
# Set JAVA_HOME export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre export PATH=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre/bin:$PATH
El directorio java debe cambiarse dependiendo la ubicacion en el ordenador.
Al editar el hadoop-env.sh, debe buscarse las siguiente dos lineas y reemplazar por:
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre
export HADOOP_OPTS=-Djava.net.preferIPv4Stack=true
Al editar el hdfs-site.xml, debe ingresarse: <property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.permission</name> <value>false</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/home/vargasde/hadoop-2.7.3/hadoop2_data/hdfs/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/home/vargasde/hadoop-2.7.3/hadoop2_data/hdfs/datanode</value> </property>
La carpeta de hadoop debe cambiarse dependiendo de la version que se utilice.
| Comando | Descripcion |
|---|---|
| ls | Lista lo que tiene en el sistema |
CopyFromLocal o Put |
Copia un arhcivo del sistema local a HDFS |
CopyToLocal o Get |
Copia un arhcivo de HDFS al local |
| hadoop fs -mkdir /nombredefolder | Genera un directorio |
| getmerge | Por cada consulta se genera un fichero por nodo ejecutado. Con este merge se ejecuta la combinacion de estos. |
| ps -aux | grep java |
| hadoop fs | Muestra todos los comandos de Hadoop |
| hdfs dfsadmin -safemode leave | Sale del safemode para el namenode |
hadoop fs -ls / |
Lista todos los folder que tiene el sistema de Hadoop. Si despues de / se escribe el nombre del folder, se accede a el |
hadoop fs -get /tutorial/libros/100_yearsofsolitude.txt GGM_100YOfSol.txt |
Saca de HDFS un archivo al ordenador |
hadoop fs -put 100_yearsofsolitude.txt /tutorial/libros |
Sube un archivo del orenador a HDFS |
Elaborado por: Diego Vargas