Archivo de la etiqueta: Mysql

performance

Mejorando el rendimiento en Drupal 7: Memcached y Entity cache

En este post vamos a enfocarnos sobre Memcached tratando de mostrar las ventajas a la hora de utilizarlo en Drupal 7.

Memcached para los que no lo conozcan, es un data cache basado en RAM.

Usar Memcached en Drupal tiene un beneficio altísimo tanto para usuarios logueados como para anónimos. ¿Por que?, fácil, Drupal para cachear utiliza la base de datos como almacén para dicho cache, y esto es costoso. Cada vez que guarda algo en cache o lo pide, estamos haciendo una query a la DB, y aunque toda tu DB este cacheada (mysql tiene su propio cache) Drupal siempre va a tener un importante overhead solo por tener que pedir a la DB este cache.

Técnicamente hablando el tema es así: Estés o no logueado, Drupal usa cache_get() y cache_set(). Luego, estas funciones delegan la tarea de cacheo a la clase que se encargue en ese momento de almacenar y devolver los datos cacheados. Una instalación estándar trae una clase llamada “DrupalDatabaseCache” que usa como backend storage la propia DB de Drupal. El módulo Memcache API simplemente proporciona su propia clase (MemCacheDrupal) que hace lo mismo pero mandando el cache a Memcache.

Memcache se presenta como una muy buena solución a este escollo ya que fue diseñado para ser usado como cache, ofreciendo un overhead mínimo y una velocidad de respuesta muy superior.

Bueno, vamos al lío.

Maquina de pruebas:

Para hacer las pruebas he usado la instalación de Drupal “Un mal día para este Drupal“.
Las pruebas las hice sobre usuarios anónimos, logueados y el propio admin que es el que mas suele sufrir en terminos de performance porque ejecuta código extra por los privilegios que conlleva.

Usuarios anónimos:

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 2312 queries in 199.42 ms.
  • Page execution time was 4791.87 ms.
  • PHP peak=59.25 MB.

Con Memcache

  • Executed 1226 queries in 71.77 ms.
  • Page execution time was 3892.39 ms.
  • PHP peak=57 MB.

Con Memcache y entity cache:

  • Executed 398 queries in 39.88 ms.
  • Page execution time was 3450.76 ms.
  • PHP peak=56 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 2312 queries in 167.15 ms.
  • Page execution time was 4037.62 ms.
  • PHP peak=59.25 MB.

Con Memcache

  • Executed 1186 queries in 66 ms.
  • Page execution time was 3927.52 ms.
  • PHP peak=57.75 MB.

Con Memcache y entity cache:

  • Executed 377 queries in 30.31 ms.
  • Page execution time was 3534.07 ms.
  • PHP peak=55.25 MB.

Usuarios logueados

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 2324 queries in 162.27 ms.
  • Page execution time was 4033.2 ms.
  • PHP peak=58.75 MB.

Con Memcache

  • Executed 1237 queries in 73.47 ms.
  • Page execution time was 4028.68 ms.
  • PHP peak=56.25 MB.

Con Memcache y entity cache:

  • Executed 396 queries in 26.19 ms.
  • Page execution time was 3530.29 ms.
  • PHP peak=56 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 2262 queries in 182.59 ms.
  • Page execution time was 4286.79 ms.
  • PHP peak=58 MB.

Con Memcache

  • Executed 1237 queries in 56.45 ms.
  • Page execution time was 3716.37 ms.
  • PHP peak=56.25 MB.

Con Memcache y entity cache:

  • Executed 379 queries in 27.97 ms.
  • Page execution time was 4072.24 ms.
  • PHP peak=55.25 MB.

Usuarios con rol “administrator”

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 3106 queries in 231.33 ms.
  • Page execution time was 5588.66 ms.
  • PHP peak=66.75 MB.

Con Memcache

  • Executed 1812 queries in 89.79 ms.
  • Page execution time was 4701.39 ms.
  • PHP peak=64.5 MB.

Con Memcache y entity cache:

  • Executed 1133 queries in 68.43 ms.
  • Page execution time was 4563.24 ms.
  • PHP peak=64.25 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 3104 queries in 219.49 ms.
  • Page execution time was 5510.96 ms.
  • PHP peak=67 MB.

Con Memcache

  • Executed 1816 queries in 107.06 ms.
  • Page execution time was 4931.99 ms.
  • PHP peak=64.25 MB.

Con Memcache y entity cache:

  • Executed 1133 queries in 71.71 ms.
  • Page execution time was 4641.69 ms.
  • PHP peak=64.25 MB.

Resumiendo:

Gráfica comparativa de Memcache y Entity cache en Drupal

Como podemos ver, cuando usamos Memcache, las queries a la db bajan un nada despreciable 50%. Estas query que ya no están, son “cache” que pasan a ser gestionadas por Memcache, quien como ya comentamos, es mucho mas eficiente a la hora de servir contenidos cacheados (insisto que está diseñado para ello, ergo es muy difícil que mysql lo haga mejor).

Pero para mas inri, al activar Entity cache, automágicamente las query a la DB bajan un 60% mas sobre lo que ya había conseguido Memcache. Esto es gracias a que este modulo implementa una capa de cache a todas las entidades del core de Drupal mas todas las entidades creadas por terceros que implementen la api en entity cache para dejarse cachear.

Conclusiones:

  • Entre Memcache y entity cache hemos logrado una reducción media del 85% de accesos a la DB (awesomeeeee!).
  • El beneficio mas evidente en el uso de Memcache y entity cache juntos es el de una reducción drástica en las
    consultas que se hacen a la DB, lo que viene especialmente bien ya que cuando una pagina en Drupal comienza a
    recibir muchas visitas, la db es lo primero que sufre.
  • Luego de estas pruebas podemos concluir que si usar Memcache es una buena idea, combinarlo con entity cache es
    una excelente idea.
  • Memcache y entity cache funcionan tanto en usuarios logueados como anónimos.
  • Es evidente que mientras mas cosas cacheemos en Drupal, mejor va a funcionar esta solución. En especial me
    refiero a views, y panels. Usen el cache que estos módulos tienen, para que Memcache pueda gestionarlos. En una
    prueba rapida que hice conseguí rebajar aun mas la cantidad de queries a solo 95 contra las 377 que ya
    lográbamos usando Memcache y entity cache
    .

Happy performance!

BD

Cómo recuperar la clave root en MySQL [Solución]. A veces pasa :D

Paramos el servidor:

sudo service mysql stop

Arrancamos “mysqld_safe”:

sudo mysqld_safe --skip-grant-tables

Dejamos esa consola con “mysqld_safe” corriendo. Abramos otra consola y hagamos lo siguiente:

sudo mysql -u root

Una vez adentro de mysql tiramos los siguientes comandos:

use mysql;
update user set password=PASSWORD("NUEVACLAVE") where User='root';
flush privileges;
quit

Ahora que hemos vuelto a la consola de linux, paramos mysql:

sudo service mysql stop

El anterior comando va a terminar el proceso “mysqld_safe” que habíamos arrancado en la primer consola, por lo que podemos cerrarla.
Listo, arrancamos mysql normalmente y ya podemos usar la nueva clave.

BD

Resetear/recuperar la contraseña del usuario “admin” con phpMyAdmin

NOTA: esta solución es útil para cualquier sistema que almacene las claves de usuarios en MYSQL por medio de MD5 o SHA1.

Hecha la aclaración, comento el caso concreto de Drupal que nos va a servir de idea para el resto:

Si no te acordás la clave de “admin” en Drupal y tenes acceso a phpMyAdmin, lo único que tenes que hacer es abrir la base de datos, localizar al usuario “admin” dentro de la tabla “usersy editarlo. Una vez que lo tengas abierto tenes que poner la clave nueva en el campo “pass”. Por ultimo solo queda decirle a phpMyAdmin que esa clave la guarde en MD5 (ver imagen).

Listo. Guarda los cambios y accede a tu usuario “admin” como de costumbre.

Drupal 6: devel generate y “Access denied”

Estas son las cosas que mas me gustan de drupal: Resolver sus “misterios”.

Resulta que estoy haciendo cientos de miles de nodos (no es broma o_O) con el modulo Devel generate para hacer unas pruebas, y cuando los creo de a 10.000 no hay problema, se tarda un huevo en hacerlos pero el batch que lanza este modulo no falla.

Pero la historia cambia cuando quiero dejar haciendo la friolera de 500.000 (quinientos mil) XD.

Bueno Marcelo deja de dar vueltas y decime que carajo pasa que no me anda bien devel generate!: ok, te cuento que resulta que Devel generate tanto como cualquier otro modulo que haga uso de batch, almacena dicho batch en la tabla correspondiente en una sola fila, osea que si son 10 ciclos de batch almacena los diez en una sola fila asi como si son 500.000. El problema se hace evidente en este punto: Me estoy excediendo en el limite que mysql tiene previsto para el envió de packets de datos.

Mysql por defecto viene configurado para recibir por fila 1MB. y esta es la parte donde les muestro esa imagen que vale mas que mil palabras :)

35.2 MB de batch…

La solución: aumentar el limite que tiene mysql claro :)

NOTA: ni en broma hagan esto en un servidor de producción salvo que sean un DBA o por lo menos tengan una clara idea de las consecuencias que implica hacer algo asi.

Para aumentar el limite simplemente tenes que seguir estos pasos: Drupal 6 XAMPP Windows XP y “MySQL Server has gone away”

BD

Tip: Restaurar un dump creado por mysql rapidamente

mysql -uUSUARIO -pCLAVE capy_db < /home/capy/Descargas/dump.sql

-uUSUARIO: nombre del usuario mysql con privilegios sobre la BD
-pCLAVE: clave del usuario
<: indicamos que vamos a lanzar el siguiente SQL sobre la BD
/home/capy/Descargas/dump.sql: Ruta hasta donde tenemos guardado el dump.

ACTUALIZACION: hacer y restaurar DB con gzip

mysqldump -uUSUARIO -pCLAVE BASE_DE_DATOS | gzip -9 > archivo_de_salida.sql.gz
gunzip < archivo_de_salida.sql.gz | mysql -uUSUARIO -pCLAVE BASE_DE_DATOS
PHP

Problemas de codificación con MySQL y PHP

No había tenido un problema asi nunca, pero en uno de los últimos proyectos se dio.

Al recuperar unos registros de la base de datos ya me estaban llegando mal codificados. Así como áóñ.

Buscando y buscando por todos lados encontré una serie de soluciones, y la combinación resultante para solucionar este problemita fue:

  • Cambiar la codificación del documento PHP a UTF-8
  • En Mysql revisar que las tablas tengan la codificación utf8_spanish_ci
  • Antes de <head></head> poner <meta http-equiv=”Content-type” content=”text/html; charset=utf-8″ />
  • Todo lo anterior es preventivo. Pero lo que realmente me dio el resultado correcto en las consultas fue poner lo siguiente entes de lanzar la consulta (en la linea que esta justo encima del mysql_db_query()):
    mysql_query(“SET NAMES ‘utf8′”);

Y listo, ya me salían bien los caratéres especiales.

1263055237_start-here-ubuntuoriginal

phpMyAdmin me dice que “Allowed memory size of xxxxx”… en Ubuntu (LAMP)

Obviamente estamos queriendo usar mas memoria de la que tenemos asignada para procesar la consulta que deseamos o cuando importamos dumps.

La solución es mas bien simple:

Para agregar mas memoria vamos a php.ini con el comando:

sudo gedit /etc/php5/apache2/php.ini

Buscamos “memory_limit” para cambiarle el limite de 16m que es lo que viene por defecto a 32M o 64M o lo que necesitemos.

Guardamos y reiniciamos Apache con el comando:

sudo /etc/init.d/apache2 restart
Druplicon

Drupal 6, $_SESSION y el usuario Anonymous

Pocas veces me encuentro con un problema tan boludo y con una solución tan sencilla.

El problema: digamos que por algún motivo tenemos que guardar información en una variable de sesision:

$_SESSION['referencia'] = "algunareferencia";

Bien,  el problema se dió cuando no lograba que el usuario “Anonymous” guardara esta variable al cambiar de página, aunque estuviera dentro del mismo sitio.

La solución:
Resulta que por algún motivo, drupal cambió el id que tiene dicho usuario de “0” a otro numero cualquiera, y eso básicamente decanta en que drupal al querer almacenar los datos de la sesision en la tabla sessions, no machea su id ya que busca la session con id 0…

En fin, la solución es simplemente editar en la tabla “users” al usuario Anonymous y cambiar su ID a 0 (si no existe el usuario solo bastaría con crear un nuevo registro con los datos en blanco, pero con ID 0).

Hacer y recuperar Dumps Mysql desde la consola

Para obtener un dump:

mysqldump --opt --password=miclave --user=miuser mibasededatos > archivo.sql

Para recuperar un dump:

mysql --password=miclave --user=miuser mibase < archivo.sql

(Reemplacen lo que esta en negrita por los datos que correspondan).

ACTUALIZACION: hacer y restaurar DB con gzip

mysqldump -uUSUARIO -pCLAVE BASE_DE_DATOS | gzip -9 > archivo_de_salida.sql.gz
gunzip < archivo_de_salida.sql.gz | mysql -uUSUARIO -pCLAVE BASE_DE_DATOS