MySQL vs PostgreSQL vs MongoDB (velocidad)

Bueno, después de algún tiempo de escuchar comentarios como “MySQL no te sirve para un sitio pequeño, PostgreSQL es mucho mejor”, o “MongoDB no es bueno”, me decidí por probar por mi mismo la velocidad de cada uno de estos motores.

Preparando la DB

Empecé colocando en cada uno, una base de datos real de tuits, que he estado recolectando desde hace unos dos años con un bot (@cuxibamba; utiliza MySQL, y, de momento, tiene 69255 tuits y 12313 usuarios)

Para colocar la base de datos de @cuxibamba en MongoDB, utilicé MongoHub, que tiene una utilidad nativa para importar de MySQL.

Tuve un poco de problemas colocando la data dentro de PostgreSQL, pero al final lo logré con taps (muy recomendado, por cierto).

Capturas de cómo inician las DB:

PostgreSQL

PostgreSQL

MySQL

MySQL

MongoDB

MongoDB

Primer test

Contando los tuits 10000 (diez mil) veces (count(*))

PostgreSQL count

PostgreSQL count

MySQL count

MySQL count

MongoDB count

MongoDB count

Resultados:

  • PostgreSQL: 164.97 segundos
  • MySQL: 151.67 segundos
  • MongoDB: 4.69 segundos (35 veces menos que PostgreSQL)

Pd. Sí, yo también me sorprendí, y revisé dos veces el script, por si me había equivocado en algo.

Segundo test

Consultando una palabra aleatoria (generada por ruby) 500 veces (where text like '%word%'). Dos partes:

  1. contar cuántas veces aparece dentro del contenido de los tuits
  2. hacer la proyección de los resultados; no solamente el conteo
PostgreSQL query random word

PostgreSQL query random word

MySQL query random word

MySQL query random word

MongoDB query random word

MongoDB query random word

Resultados:

  • PostgreSQL: 20.71 segundos al contar cuántos resultados (count()), 20.77 segundos al hacer la proyección de los resultados y asignar a una variable cada uno.
  • MySQL: 26.4 segundos al contar cuántos resultados (count()); 69.91 segundos al hacer la proyección y asignar los resultados a variables.
  • MongoDB: 63.7 segundos al contar los resultados (count()); 65.08 segundos al hacer la proyección y asignar los resultados.

Conclusiones de este test:

  1. PostgreSQL se toma el mismo tiempo en hacer un conteo de los datos que coinciden con los criterios, que cuando selecciona los datos. Logró un muy buen tiempo en este test.
  2. MySQL se toma mucho menos tiempo cuando cuenta cuántas tuplas coinciden con el criterio, que cuando selecciona cada tupla para utilizarla luego
  3. MongoDB se tomó mucho más tiempo en este test. Probablemente esto sea culpa mía; no pude encontrar un equivalente a: select * from tweets where text like '%word%'; en mongo; en su lugar, estoy utilizando una expresión regular, la cual, obviamente va a coincidir con más resultados y va a costar más recursos.

Tercer test

Select buscando por id (primary key) 1000000 (un millón) veces (los ids son generados aleatoriamente por ruby entre 1 y 69255).

PostgreSQL find by id

PostgreSQL find by id

MySQL find by id

MySQL find by id

MongoDB find by id

MongoDB find by id

Resultados:

  • PostgreSQL: 763.98 segundos
  • MySQL: 652.39 segundos
  • MongoDB: 552.51 segundos

Cuarto test

En mi opinión, el más importante: el CRUD, compuesto por lo siguiente:

  1. Crear 10000 (diez mil) tuits.
  2. Encontrarlos (por su id único) y actualizar su texto (guardándolo en DB nuevamente).
  3. Encontrar nuevamente los 10000 tuits y actualizar tres veces el contenido de cada uno, guardando en DB cada vez que se actualice. (Es decir, tres veces por tuit)
  4. Encontrar cada uno de los 10000 tuits (por su id) y eliminarlo 
PostgreSQL CRUD

PostgreSQL CRUD

MySQL CRUD

MySQL CRUD

MongoDB CRUD

MongoDB CRUD

Resultados:

  • PostgreSQL:
    • 38.82 segundos para almacenar diez mil tuits
    • 35.45 segundos para encontrar y actualizar diez mil tuits
    • 106.39 segundos para encontrar los tuits y actualizar tres veces cada uno
    • 23.54 segundos para eliminar los tuits
    • Total: 204.2 segundos
  • MySQL:
    • 40.18 segundos para almacenar diez mil tuits
    • 29.71 segundos para encontrar y actualizar diez mil tuits
    • 87.32 segundos para encontrar los tuits y actualizar tres veces cada uno
    • 22.55 segundos para eliminar los diez mil tuits
    • Total: 179.76 segundos
  • MongoDB:
    • 4.81 segundos para almacenar diez mil tuits
    • 18.13 segundos para encontrar y actualizar diez mil tuits
    • 54.86 segundos para encontrar los tuits y actualizar tres veces cada uno
    • 14.9 segundos para eliminar diez mil tuits
    • Total: 92.7 segundos (casi la mitad de MySQL, menos de la mitad de PostgreSQL)

Conclusiones: (?)

  • MongoDB rocks, NoSQL rocks (sí, soy fanboy)
  • MongoDB podría llegar a ser el doble de rápido comparado con MySQL y PostgreSQL (?)
  • En el segundo test, como detallé, MongoDB se queda atrás por bastante porque no he podido encontrar (todavía) una manera de hacer where field like %text% (probablemente debe haberla); y tuve que utilizar una expresión regular que disparó el consumo de recursos
  • MySQL es más rápido que PostgreSQL, excepto cuando tiene que hacer una proyección con una (o varias) condiciones (where). Será que PostgreSQL indexa mejor los datos? (ver segundo test)
  • A PostgreSQL le costó bastante actualizar la información de cada tuit (último test)

Espero que les sirva de algo. El hardware de mi Mac es:

  • Procesador: 2.3 Ghz Intel Core i7
  • Memoria: 8GB 1600Mhz DDR3
  • HD: APPLE SSD SM256E Media ( ~500MB/s )

Instalando Ruby(1.9.3) on Rails(3.2.2) en Ubuntu Server 11.10 (y de cómo solucioné los errores)

Son las 17:50. Empecé a las 13:20. ¡Lo hice!

Error con RoR y zlib

Error con RoR y zlib

ERROR: Loading command: install (LoadError)
cannot load such file -- zlib
ERROR: While executing gem ... (NameError)
uninitialized constant Gem::Commands::InstallCommand

En estas épocas del año, que me encuentro desarrollando en Ruby on Rails, me ha tocado montar otro servidor que utilizaremos en producción con un proyecto que tengo. Ha sido un largo trabajo. He tenido errores, pero los he solucionado (justo cuando estaba a punto de rendirme).

  1. He instalado un Ubuntu Server y he escogido los paquetes LAMP (para mis proyectos utilizaré Apache y MySQL con RoR).
  2. Instalamos el paquete que nos permitirá compilar y librerías de YAML:
    macool@shiriculapo.local:~$ sudo apt-get install build-essential libyaml-dev zlib1g-dev libreadline-dev libopenssl-ruby libssl-dev
  3. Descargamos el código fuente de Ruby (1.9.3):
    macool@shiriculapo.local:~$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p0.tar.gz
  4. Descomprimimos el paquete de código fuente que acabamos de descargar:
    macool@shiriculapo.local:~$ tar xzvf ruby-1.9.3-p0.tar.gz
    Nos cambiamos a la carpeta que acabamos de descomprimir:
    macool@shiriculapo.local:~$ cd ruby-1.9.3-p0
  5. Esta es la parte importante.Antes de realizar este paso, estuve toda la tarde probando un millón de posibles soluciones, incluyendo:
    • utilizar rvm de mil maneras
    • instalar miles de librerías relacionadas con zlib
    • instalar ruby, rubygems y rails desde el repositorio, con apt-get install ruby-full rubygems rails
    • compilar zlib manualmente y especificarlo al momento de configurar ruby para su compilación
    • otras

    No pierdan su tiempo, ni el mío. No hablaré acerca de ninguna de estas “soluciones”; no funcionan. Haremos algo más sencillo, que es lo que a mi me resultó.
    Descomentaremos una línea en la que ruby (por defecto) ignora zlib. Yo soy un fan de GNU, y utilizaré nano(un editor de texto de terminal), pero ustedes pueden utilizar cualquier editor:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ nano ext/Setup
    Aquí, vamos a la última línea y descomentamos zlib, como en la imagen:

    descomentando zlib

    descomentando zlib

    En nano, cierro el archivo con CTRL+X (y lo guardo)

  6. Configuramos las librerías que ruby necesita para que coincidan con las de nuestro servidor:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ ./configure
    Una vez configurado, compilamos ruby:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ sudo make
    … E instalamos ruby:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ sudo make install
    En este punto, ruby ya debe estar instalado:

    ruby -v

    ruby -v (versión de ruby)

  7. Esta es la otra parte importante. Instalamos zlib. Nos cambiamos a la carpeta ext/zlib dentro del código fuente de ruby:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ cd ext/zlib/
    Configuramos las librerías de zlib:
    macool@shiriculapo.local:~/ruby-1.9.3-p0/ext/zlib$ ruby extconf.rb
    Compilamos zlib:
    macool@shiriculapo.local:~/ruby-1.9.3-p0/ext/zlib$ make
    Instalamos zlib:
    macool@shiriculapo.local:~/ruby-1.9.3-p0/ext/zlib$ sudo make install
  8. Ahora, vamos por rubygems. Salimos de la carpeta de ruby:
    macool@shiriculapo.local:~/ruby-1.9.3-p0$ cd ..
    Descargamos el código fuente al servidor:
    macool@shiriculapo.local:~$ wget http://production.cf.rubygems.org/rubygems/rubygems-1.8.21.tgz
    Descomprimimos el código fuente de rubygems (que acabamos de descargar):
    macool@shiriculapo.local:~$ tar xzvf rubygems-1.8.21.tgz
    Nos cambiamos a la carpeta del código fuente de rubygems:
    macool@shiriculapo.local:~$ cd rubygems-1.8.21
  9. Instalamos rubygems:
    macool@shiriculapo.local:~/rubygems-1.8.21$ sudo ruby setup.rb
    Salimos de la carpeta de rubygems:
    macool@shiriculapo.local:~/rubygems-1.8.21$ cd ..
    rubygems debe estar instalado:

    gem -v

    gem -v (versión de rubygems)

    En este punto, ya podemos eliminar todo lo que acabamos de descargar; no nos servirá para nada más

  10. Instalamos rails (con rubygems, se deberían instalar todas sus dependencias):
    macool@shiriculapo.local:~$ sudo gem install rails

    rails -v

    rails -v (versión de rails)

Eso es todo :)

Plano digital de Loja (2D)

Espero que esto le sea útil a alguien. coloco un enlace a un plano de la ciudad de Loja en 2D.

El archivo se encuentra en formato .dwg, para ser abierto por programas de CAD, tales como AutoCad.

Actualización:

Lo siento. Cambié de servidor y perdí el archivo. Si lo encuentras, ponme un comentario.

Cuando El Colegio Técnico Atahualpa, de Ambato, fue hackeado

Hace un par de días, mientras leía, encontré que ciertas versiones antiguas de Joomla tienen serios fallos de seguridad y son, teóricamente, muy vulnerables a ataques de hacking. Sabiendo esto, me nació la curiosidad de hackear algún Joomla del país. El objetivo fue  http://colegioatahualpaambato.edu.ec ; sucede que la versión de Joomla que tienen instalado es antigua, y tiene muchos fallos de seguridad.

Ahora, una captura de pantalla:

Colegio Atahualpa hacked

Colegio Atahualpa hacked

 
:)
Bueno, la verdad es que espero que lo tomen como una advertencia a lo que podría sucederles más adelante, si no actualizan Joomla, mas no como una fechoría