Professional Documents
Culture Documents
y corre
Las operaciones sobre bases de datos suelen ser los principales cuellos de botella en las aplicaciones web. Por tanto es tarea de los programadores estructurar apropiadamente, escribir peticiones apropiadas, y programar mejor cdigo. A continuacin mostramos algunas tcnicas de optimizacin MySQL.
la razn por la que no funciona en el primer caso es por el uso de CURDATE(). Puede aplicarse a todas las funciones no deterministas, como NOW() y RAND(). Dado que el resultado retornado por la funcin puede cambiar, MySQL decide deshabitar la cach en esa consulta.
El resultado de una query EXPLAIN te mostrar los ndices que se estn utilizando, cmo se est explorando la tabla, cmo se est ordenando, etc Coge una consulta SELECT (preferiblemente una compleja, con uniones), y aade la palabra EXPLAIN al principio del todo. Puedes utilizar por ejemplo PhpMyAdmin para esto. Te devolver los resultados en una sencilla tabla. Por ejemplo, pongamos que me he olvidado de poner un ndice a una columna, con la que estoy ejecutando
Ahora en lugar de escanear 7883 filas, slo escanear 9 y 16 filas de las dos tablas.
. . // lo que NO hay que hacer: . $r = mysql_query("SELECT * FROM user WHERE ciudad = Valencia"); . if (mysql_num_rows($r) > 0) { . . } . . // mucho mejor: . $r = mysql_query("SELECT 1 FROM user WHERE ciudad = Valencia LIMIT 1"); . if (mysql_num_rows($r) > 0) { . . } // //
Como puedes ver, esta regla se aplica tambin a las bsquedas parciales como apellido LIKE a%. Cuando se busca desde el comienzo de la cadena, MySQL es capaz de utilizar el ndice de esta columna. Deberas tambin comprender en qu tipos de bsqueda no pueden utilizarse ndices normales. Por ejemplo, cuando buscas una palabra dentro de un texto (p.e. WHERE contenido LIKE %manzana%), no observars ningn beneficio con un ndice normal. En este caso sera mejor utilizar una bsqueda FULLTEXT o construir tu propia solucin de indexacin.
. $r = mysql_query("SELECT nombre_companyia FROM usuarios . . . . // ambas columnas ciudad deben estar indexadas . // y ambas deberan ser del mismo tipo y codificacin de caracteres . // o MySQL tendr que hacer un escaneo total de las tablas LEFT JOIN companyias ON (usuarios.ciudad = companyias.ciudad) WHERE usuarios.id = $user_id");
De forma que seleccionas un nmero aleatorio inferior a la cantidad de resultados y lo usas como el desplazamiento en la clusula LIMIT.
7. Evita SELECT *
Cuanta ms informacin se lee de las tablas, ms lenta se ejecutar la peticin SQL. Aumenta el tiempo que toma para las operaciones en disco. Adems cuando el servidor de bases de datos est separado del servidor web, tendrs mayores retrasos de red debido a que la informacin tiene que ser transferida entre ambos servidores. Es un buen hbito especificar siempre las columnas que necesitas cuando ests haciendo un SELECT.
. // preferible no hacer: . $r = mysql_query("SELECT * FROM usuarios WHERE id_usuario = 1"); . $d = mysql_fetch_assoc($r); . echo "Bienvenido {$d['nombreusuario']}"; . . // mejor: . $r = mysql_query("SELECT nombreusuario FROM usuarios WHERE id_usuario = 1"); . $d = mysql_fetch_assoc($r);
. echo "Bienvenido {$d['nombreusuario']}"; . . // las diferencias son mucho ms significativas cuanta ms informacin haya
Ten presente que esto son slo sugerencias. Y si tu tabla va a crecer mucho, podran no ser buenas sugerencias a seguir. La decisin es tuya en ltima instancia.
Hubo un tiempo en que muchos programadores solan evitar las declaraciones preparadas a propsito, por una nica razn: no estaban siendo cacheadas por la cach de consultas de MySQL. Pero aproximadamente en la versin 5.1, el cacheo de consultas tambin ha sido soportado. Para utilizar declaraciones preparadas en PHP puedes echar un ojo a la extensin mysqli o utilizar una capa de abstraccin de base de datos como PDO.
. // creamos la declaracin preparada . if ($stmt = $mysqli->prepare("SELECT nombre FROM usuarios WHERE ciudad=?")) { . . . . . . . . . . . . . . . . . } $stmt->close(); printf("%s es de %s\n", $nombre, $ciudad); // obtenemos el resultado $stmt->fetch(); // pasamos la variable de resultado $stmt->bind_result($nombre); // ejecutamos $stmt->execute(); // pasamos los parmetros $stmt->bind_param("s", $ciudad);
Muchos programadores crearan un campo VARCHAR(15) sin darse cuenta de que pueden almacenar las direcciones IP como nmeros enteros. Cuando usas un INT slo haces uso de 4 bytes en la memoria, y cuenta adems con un tamao fijo en la tabla. Pero hay que asegurarse de que la columna sea UNSIGNED INT (entero sin signo) porque las direcciones IP hacen uso de todo el rango de 32 bits sin signo. En tus consultas puedes utilizar la funcin INET_ATON() para convertir una direccin IP en entero, e INET_NTOA() para hacer lo contrario. Tambin existen funciones parecidas en PHP llamadas ip2long() y long2ip().
. $r = "UPDATE users SET ip = INET_ATON({$_SERVER['REMOTE_ADDR']}) WHERE user_id = $user_id";
Si necesitas ejecutar una consulta DELETE o INSERT que sea grande en una pgina web activa, tienes que tener cuidado de no alterar el trfico web. Cuando una consulta grande como esas se ejecuta, puede bloquear tus tablas y paralizar tu aplicacin web momentaneamente. Apache ejecuta muchos procesos/hilos paralelamente. De ah que funcione mucho ms eficientemente cuando los scripts dejan de ejecutarse tan pronto como es posible, para que los servidores no experimenten muchas conexiones abiertas y procesos de una que consumen recursos, especialmente memoria primaria. Si en algn momento bloqueas tus tablas en un periodo largo (como 30 segundos o ms), en una web con mucho trfico, causars un apilamiento de procesos y consultas, que llevar mucho tiempo de concluir o que incluso podra estropear tu servidor web. Si tienes algn script de mantenimiento que tiene que borrar una gran cantidad de filas, simplemente utiliza la clusula LIMIT para hacerlo en porciones ms pequeas y as evitar la congestin.
. while (1) { . . . . . . . . } } // incluso viene bien parar un poco usleep(50000); mysql_query("DELETE FROM logs WHERE log_date <= 2009-10-01 LIMIT 10000"); if (mysql_affected_rows() == 0) { // finalizado el borrado break;
24 agosto 12:17 Alex Barros Ha dicho: A las queries DELETE y UPDATE se aplica el punto 17: 17. Divide las consultas DELETE o INSERT grandes No es necesario usar LIMIT 1, pero s segmentarlo cuando son muy grandes. 26 agosto 21:27 alejo Ha dicho: Muy buen articulo, siempre es bueno aprender algo mas. Saludos! 10 septiembre 17:52 Claudio Ha dicho: Agregara algo al punto 7. - No es recomendable select * por que obligas al motor a leer la estructura de la tabla para conocer los nombres de los campos. 10 enero 1:22 Rodrigo Ha dicho: Excelente! Muchas gracias por tu tiempo, me ha servido mucho. 9 febrero 18:02 Angel Aparicio Ha dicho: Muy interesante, gracias. Algunas son tan de cajn, como la de poner LIMIT 1 cuando solo quieres un elemento, que es darte de collejas por no haberla estado usando antes. Muy interesantes tambin el puntos del particionamiento vertical. Hace un par de semanas le un artculo sobre como haban optimizado Reddit para poder soportar el trfico que tienen y una de las claves era esa, tablas muy bsicas con la informacin mnima de cada elemento y tablas auxiliares con los detalles de cada cosa. O algo as, cito de memoria (y no encuentro el enlace) 3 marzo 15:10 Pedro Ha dicho: Particionado vertical
Enviar
Search:
Buscar
Bicivalencia Localiza las estaciones de Valenbisi, servicio pblico de bicicletas en Valencia, Espaa. Ver ms Gpsia Descubre y comparte rutas por todo el mundo, tomadas con GPS. Ver ms Imaset Edita tus imgenes de Wordpress con este sencillo plugin. Ver ms
Mi msica es tuya!
Experimentos BSO TMEC Como la vida - Hanna Crash! - Propellerheads Broken Dreams (acstica) - Basement Jaxx
Digo yo que...
sgueme!
w w w .flickr .com
Entradas recientes
20 Consejos para Mejorar tu MySQL que quizs no conocas API de Valenbisi (Servicio de JCDeacaux) Defensa a ultranza del Software Libre Mltiples join y solucin al encadenar LEFT JOINS 5 mximas Por qu cambio el cdigo por la cmara de vdeo? Proyectos on progress Ir a la Valencia Pillow Fight Script PHP para explorar archivos y directorios recursivamente Retomando Gpsia con fuerza
Meta:
Acceder RSS RSS de los comentarios