Siguiendo con el “espíritu” del apunte anterior. Txipi hizo diana, sí, se trata del artículo de Joel Spolsky “volver a lo básico”. Para alguien que no conoce esas bases, ni cómo funcionan los strings enseguida dice “vaya chapuza”, si eso se puede hacer con la clase XYZStringOnSteroids o con un buen SQL estándar…
[1] Alerta, aunque hay optimizaciones imprescindibles, la mayoría son prematuras, las madres de todos los males.
Hablando de SQL, en los últimos meses aprendí mucho de sql, pero sobre todo cuando hay que saltarse el “camino obvio” y buscar un hack para aquellas optimizaciones imprescindibles. Una que me paso hace pocas horas con el nuevo modelo de tres columnas del Menéame, en particular con la generación de las etiquetas que aparecen arriba a la derecha.
Seguramente para los expertos en bbdd es una tontería como una casa, pero para mí no fue obvio, es como el tema de seguridad. No es que te enseñan unas reglas y ya está, debes asumirlas e integrarlas en el proceso de desarrollo. Lo mismo me pasó con muchas cosas del SQL, especialmente del SQL, cuando se trata de generar una decenas de páginas por segundo, lo más rápido posible, aunque cada una tenga decenas de consultas a la bbdd.
Lo último, para ver si lo sabéis –expertos abstenerse, sólo dejad la pista
–. Aquí se observa la última modificación que hice a esa función. En la columna de la izquierda se observa en amarillo el código que fue modificado por el de la derecha (sólo interesa la primera línea).
El de la izquierda ya es “raro”, ya que es un sql adicional. Pero el de la derecha es aún más bizarro para alguien que nunca lo haya pensado. ¿Por qué están ambos códigos? ¿por qué quedó como está? (sí, ya, es una optimización como dice el “log”).
PS: Curioso los trucos que hay que aprender a usar, sin algunos de los dos quizás hubiese tenido que quitar lo de las etiquetas porque el servidor no hubiese aguantado, al menos en horas pico. Hace un año atrás no se me hubiese ocurrido esta solución para quitar muuuuuuucho trabajo a la bbdd.
Actualización/Respuesta: es la cache
MySQL tiene un sistema de cache de consultas SQL. Para un web como el menéame, con cientos de consultas por segundo, esta cache es fundamental para no recargar el servidor. En el caso mostrado se trata de contar cuáles son las etiquetas más repetidas en las últimas 48 horas, lo que significa recorrer la tabla de etiquetas (tags) y contar unos pocos miles de etiquetas.
Si esa consulta se repitiese para cada página que se genera el servidor se cargaría demasiado. Por ello es indispensable que estén en cache. Una forma de consulta habitual es usar el date_sub, por ejemplo:
date > date_sub(now(), interval 48 hour)
Pero tiene un problema, el “now()” es un dato que varía constantemente, por ello el mysql no cachea estas consultas. Para permitir que se haga lo mejor es seleccionar una fecha que permanezca constante durante un tiempo razonable.
Por ello primero use una fecha de noticia publicada y luego lo simplifiqué a la hora actual (sin minutos ni segundos) menos 48 horas. Así se puede mantener en cache la consulta hasta una hora si es que no hay cambios en las tablas.
Para todo el desarrollo del menéame fui con mucho cuidado en permitir la máxima cantidad de cache posible, y cuando se sabe que no tiene sentido el cache (por ejemplo cuando verifica la IP de cada cliente) lo obligo a saltarse con el SQL_NO_CACHE para evitar gastar tiempo y sobre todo memoria. Por ejemplo en el control de votos de cada usuario:
SELECT SQL_NO_CACHE count(*) FROM votes WHERE $where
Por lo demás, tengo configurado el mysql para usar 24 MB de RAM (antes tenía 16) para el cache de SQL.