statement - sentencias preparadas php mysqli
¿Debo usar declaraciones preparadas para MySQL en PHP PERFORMANCE-WISE? (5)
Entiendo los beneficios de seguridad de las declaraciones preparadas en MySQL. No es necesario que cubras ese tema aquí. Me pregunto sobre el aspecto de rendimiento de ellos.
Ahora, sé que cuando una consulta que utiliza una declaración preparada se ejecuta dos veces en una sola secuencia de comandos PHP, es más rápida porque la consulta solo se analiza una vez, una para cada consulta. El cliente hace un viaje para prepararse, luego envía datos dos veces usando el protocolo binario. El protocolo binario es más rápido, y no estás teniendo el éxito de tener que analizar por segunda vez.
Sin embargo, ¿qué pasa con el caso en el que solo quiero realizar una consulta una vez en un único script PHP? Parecería que usar una declaración preparada es peor, porque estás haciendo dos viajes al servidor, una para preparar y otra para enviar los datos. Se pierde el beneficio de solo tener que analizar una vez, y se te penaliza por ese segundo viaje. Si los datos no son lo suficientemente pequeños en formato binario, pierde utilizando una declaración preparada, ¿verdad?
Sin embargo, he leído algunos informes contradictorios sobre lo que hacen las bibliotecas mysqli o PDO de PHP. ¿Alguno de ellos almacena en caché la sentencia preparada en la ejecución del script? ¿El servidor va a tener que analizar la declaración preparada nuevamente en una carga de página posterior o no? Si la respuesta es no, que la declaración no tiene que ser analizada en la segunda carga de página, entonces parecería que las declaraciones preparadas SON mejores, incluso si solo está ejecutando la consulta una vez por descarga de página.
Tenga en cuenta si algo ha cambiado entre las versiones de MySQL con respecto a esto. Puedes asumir que estoy usando PHP 5.2
EDITAR: Para dejarlo en claro, quiero una respuesta para MySQL y PHP específicamente, especificando la versión de MySQL y si esto alguna vez fue diferente, y SÓLO considero el rendimiento, no la facilidad de uso o la seguridad.
ACTUALIZACIÓN: Acepté la respuesta que hice debido al comentario de seguimiento que tuvo algunas buenas ideas. Todavía estoy un poco decepcionado de que nadie parece ser capaz de responder el quid de la pregunta real que hice con certeza. Supongo que a veces la respuesta es "depende".
La historia
Esta fue mi primera respuesta . Mucho ha cambiado desde entonces, especialmente la depreciación y eliminación de la API mysql. Incluso si todavía está en php 5.6, la API mysql_ * no debe ser utilizada. Ahora PDO o mysqli son las únicas opciones para elegir. PDO es mejor por muchas razones.
¿Las declaraciones preparadas se almacenan en caché en las cargas de página?
He leído algunos informes contradictorios sobre lo que hacen las bibliotecas mysqli o PDO de PHP. ¿Alguno de ellos almacena en caché la sentencia preparada en la ejecución del script?
La misma declaración preparada no se usará entre cargas de página. Tiene que estar preparado todo el tiempo. Si exprime cada milisegundo importante, un procedimiento almacenado podría ser una buena idea (suponiendo que tenga una consulta complicada).
Para inserciones grandes (miles de filas) Es probable que se obtenga un aumento mayor si se vuelcan los datos en un archivo de texto y se carga con LOAD DATA IN FILE. Es mucho más rápido que una serie de insertos.
La respuesta original
La verdad del asunto es que a veces mysqli es más rápido y otras veces mysql api es más rápido. Pero la diferencia es realmente muy pequeña. Si observa cualquiera de las pruebas de rendimiento en la web, la diferencia es realmente de 10 a 20 milisegundos. La mejor forma de aumentar el rendimiento es optimizar el diseño de la mesa.
Muchas de las pruebas que "prueban" que la API más vieja es más rápida convenientemente olvida que para una seguridad máxima se debe invocar a mysql_real_escape_string () para cada variable utilizada en la consulta.
Las consultas son almacenadas en caché por el servidor, si y solo si los datos en todas las tablas que se utilizan en la consulta se han mantenido sin cambios.
Esperar otra actualización con números reales
"Usar declaraciones preparadas nunca es realmente una mala idea"
No es verdad. Puede llenar fácilmente el caché de declaraciones preparado y superar max_prepared_stmt_count
si no sabe lo que está haciendo, haciendo que su aplicación sea inútil hasta que se cierren las conexiones que consumen las declaraciones preparadas.
Los enunciados preparados están diseñados específicamente para bucles internos ajustados en su lógica de negocio donde llamará a la misma consulta básica una y otra vez, un buen ejemplo es una consulta parametrizada como:
SELECT name, address, phone from tbl WHERE id = ?
y tiene una identificación diferente en cada llamada. De esta forma, vale la pena el viaje adicional a la base de datos para la preparación, porque es probable que lo llames cientos o miles de veces y simplemente cambies el parámetro. Pero se espera que elimine la declaración preparada de la memoria caché o cierre la conexión al final de, por ejemplo, su secuencia de comandos sin estado (php, perl, jsp, ruby, etc.).
Si no elimina la declaración preparada y está utilizando una agrupación de conexiones, está obligado a completar la memoria caché a lo largo del tiempo y obtendrá un desagradable error "No se pueden crear más que las declaraciones max_prepared_stmt_count". Hablo por experiencia, así que piense si realmente necesita declaraciones preparadas porque sabe de manera definitiva que va a repetir la misma consulta parametrizada una y otra vez en un círculo cerrado.
Si no, lo que probablemente estés buscando es dejar que mysql use su caché de consultas básicas, que es un mecanismo diferente de la lista de declaraciones preparadas y que se comporta como un verdadero caché de LRU, según entiendo.
¿Qué quiere decir exactamente "analizado en la segunda página"?
Cada proceso PHP / thread / visitante que ejecuta el mismo script de nuevo NO evitará que MySQL vuelva a analizar la consulta para prepararla, ya que es válida por conexión, por lo que es muy efectiva para consultas repetidas en el mismo script.
Ahora, no puedo discutir acerca de cómo preparar + ejecutar frente a consulta simple, en cuanto al rendimiento (sin consultas repetidas);
Pero, para evitar que mysql analice una consulta compleja en cada ejecución de script, debe usar procedimientos almacenados; una consulta sería solo CALL items(date,search_etc,id);
en lugar de SELECT i.id FROM products as p JOIN item_prodct as t ON... JOIN items as i... ON... WHERE ... p.date ... i.search_etc ...
Puede usar procedimientos almacenados con declaraciones preparadas.
No para todos los casos. Hay momentos en los que las declaraciones preparadas tienen un rendimiento más lento que una consulta construida manualmente aunque se ejecute repetidamente .
Por ejemplo, cuando necesito insertar cientos de filas en una carga de página, encuentro:
$pdo -> query("INSERT INTO table (field1, field2, ...) VALUES (".$pdo -> quote($value1).", ".$pdo -> quote($value2).", ...), (row2), (row3), ..., (row100), ...");
Mucho más rápido que:
$stmt = $pdo -> prepare("INSERT INTO table (field1, field2, ...) VALUES (:value1, :value2, ...)");
foreach (/* some hundred times */) {
$stmt -> execute(array(''value1'' => $value1, ''value2'' => $value2, ...));
}
ACTUALIZAR
Escribí esta respuesta hace 4 años, desde entonces aprendí cosas nuevas sobre esto.
Para la sentencia preparada que se ejecuta repetidamente cientos de veces para ser rápida, debe ajustar todas las ejecuciones en una transacción .
Sin embargo, nunca probé cuál es el INSERT más rápido, no preparado de un solo lote con 1000 filas o 1000 ejecuciones de INSERT preparado envuelto en una transacción.
Usar declaraciones preparadas nunca es realmente una mala idea. No los he usado recientemente con mySQL, pero los he usado mucho con SQLSERVER, y funcionan muy bien.
La biblioteca PDO probablemente no haga ningún almacenamiento en caché, pero la base de datos lo hará para la declaración preparada.
Además, como cubriste, son geniales para la seguridad. También es muy agradable sacar esa lógica del código; no se aplica SQL salpicado en toda la aplicación.