ventajas stmt statement sentencias prepared preparadas desventajas bind_param java database performance prepared-statement

java - stmt - sentencias preparadas php pdo



Declaraciones preparadas y rendimiento (10)

Entonces, ¿cómo ayuda con el rendimiento? ¿El controlador almacena en caché la declaración precompilada y me da una copia la próxima vez que haga connection.prepareStatement? ¿O ayuda el servidor DB?

Voy a responder en términos de rendimiento. Otros aquí ya han estipulado que PreparedStatement s es resistente a la inyección de SQL (ventaja bendecida).

La aplicación (Controlador JDBC) crea PreparedStatement y la pasa a RDBMS con marcadores de posición ( ? el ? ). El RDBMS precompila, aplicando optimización de consulta (si es necesario) de la PreparedStatement recibida y (en algunos) generalmente los almacena en caché. Durante la ejecución de PreparedStatement , se utiliza PreparedStatement precompilado, reemplazando cada marcador de posición con sus valores relevantes y calculados. Esto contrasta con Statement que lo compila y lo ejecuta directamente, PreparedStatement compila y optimiza la consulta una sola vez . Ahora, este escenario explicado anteriormente no es un caso absoluto para TODOS los proveedores de JDBC, pero en esencia así es como se utiliza y se opera PreparedStatement .

Por lo tanto, sigo escuchando que las declaraciones preparadas son buenas para el rendimiento.

Tenemos una aplicación Java en la que usamos la ''Declaración'' más que la ''Preparación''. Al intentar avanzar hacia el uso de más PreparedStatements, estoy tratando de obtener una comprensión más completa de cómo funcionan los PreparedStatements - en el lado del cliente y del lado del servidor.

Entonces, si tenemos algunas operaciones CRUD típicas y actualizamos un objeto repetidamente en la aplicación, ¿ayuda el uso de un PS? Entiendo que tendremos que cerrar el PS cada vez que, de lo contrario, se producirá una fuga del cursor.

Entonces, ¿cómo ayuda con el rendimiento? ¿El controlador almacena en caché la declaración precompilada y me da una copia la próxima vez que haga connection.prepareStatement? ¿O ayuda el servidor DB?

Entiendo el argumento sobre los beneficios de seguridad de PreparedStatements y aprecio las respuestas a continuación que lo enfatizan. Sin embargo, realmente quiero mantener esta discusión centrada en los beneficios de rendimiento de PreparedStatements.

Actualización: cuando digo datos de actualización, realmente me refiero a más en términos de que el método se llame varias veces al azar. Entiendo la ventaja en la respuesta ofrecida a continuación, que solicita reutilizar la declaración dentro de un bucle.

// some code blah blah update(); // some more code blah blah update(); .... public void update () throws SQLException{ try{ PreparedStatement ps = connection.prepareStatement("some sql"); ps.setString(1, "foobar1"); ps.setString(2, "foobar2"); ps.execute(); }finally { ps.close(); } }

No hay forma de reutilizar realmente el objeto java ''ps'' y entiendo que la llamada connection.prepareStatement real es bastante costosa.

Que es lo que me hace volver a la pregunta original. ¿Es este "algunos sql" PreparedStatement todavía se almacena en caché y se reutiliza bajo las cubiertas que no conozco?

También debo mencionar que apoyamos varias bases de datos.

Gracias por adelantado.


Analizar el SQL no es lo único que está sucediendo. Se está validando que las tablas y columnas sí existen, creando un plan de consulta, etc. Se paga una vez con una declaración preparada.

Enlazar para protegerse contra la inyección de SQL es algo muy bueno, por cierto. No es suficiente, OMI. Aún debe validar la entrada antes de llegar a la capa de persistencia.


Anecdóticamente: hice algunos experimentos con declaraciones preparadas frente a dinámicas utilizando ODBC en Java 1.4 hace algunos años, con back-ends de Oracle y SQL Server. Descubrí que las declaraciones preparadas podían ser hasta un 20% más rápidas para ciertas consultas, pero había diferencias específicas de cada proveedor respecto de qué consultas se habían mejorado en qué medida. (Esto no debería ser sorprendente, en realidad.)

La conclusión es que si reutilizará la misma consulta repetidamente, las declaraciones preparadas pueden ayudar a mejorar el rendimiento; pero si su desempeño es lo suficientemente malo como para que deba hacer algo al respecto de inmediato, no cuente con el uso de declaraciones preparadas para darle un impulso radical. (20% generalmente no es nada del otro mundo).

Su kilometraje puede variar, por supuesto.


La noción de que las declaraciones preparadas tienen que ver principalmente con el desempeño es algo así como un concepto erróneo, aunque es bastante común.

Otro póster mencionó que notó una mejora en la velocidad de alrededor del 20% en Oracle y SQL Server. He notado una figura similar con MySQL. Resulta que analizar la consulta simplemente no es una parte tan importante del trabajo involucrado. En un sistema de base de datos muy ocupado, tampoco está claro que el análisis de consultas afecte el rendimiento general: en general, es probable que solo consuma tiempo de CPU que, de lo contrario, estaría inactivo mientras los datos regresaban del disco.

Por lo tanto, como una razón para usar declaraciones preparadas, la protección contra los ataques de inyección de SQL supera con creces la mejora de rendimiento. Y si no está preocupado por los ataques de inyección SQL, probablemente debería ...


Las declaraciones preparadas pueden mejorar el rendimiento al reutilizar la misma declaración que usted preparó:

PreparedStatement ps = connection.prepare("SOME SQL"); for (Data data : dataList) { ps.setInt(1, data.getId()); ps.setString(2, data.getValue(); ps.executeUpdate(); } ps.close();

Esto es mucho más rápido que crear la declaración en el bucle.

Algunas plataformas también almacenan en caché las declaraciones preparadas para que, incluso si las cierra, se puedan reconstruir más rápidamente.

Sin embargo, incluso si el rendimiento fuera idéntico, debería utilizar las declaraciones preparadas para evitar la inyección SQL. En mi compañía esta es una pregunta de entrevista; Hazlo mal y puede que no te contratemos.


Las declaraciones preparadas se almacenan en caché después de su primer uso, que es lo que proporcionan en el rendimiento sobre las declaraciones estándar. Si su declaración no cambia, entonces se recomienda utilizar este método. Por lo general, se almacenan dentro de un caché de instrucciones para su uso posterior.

Aquí se puede encontrar más información:

http://www.theserverside.com/tt/articles/article.tss?l=Prepared-Statments

y es posible que desee ver Spring JDBCTemplate como una alternativa al uso de JDBC directamente.

http://static.springframework.org/spring/docs/2.0.x/reference/jdbc.html


Las declaraciones preparadas tienen algunas ventajas en términos de rendimiento con respecto a las declaraciones normales, dependiendo de cómo las use. Como alguien dijo anteriormente, si necesita ejecutar la misma consulta varias veces con diferentes parámetros, puede reutilizar la declaración preparada y pasar solo el nuevo conjunto de parámetros. La mejora del rendimiento depende del controlador específico y la base de datos que está utilizando.

Como ejemplo, en términos de rendimiento de la base de datos, la base de datos Oracle almacena en caché el plan de ejecución de algunas consultas después de cada cálculo (esto no es cierto para todas las versiones y toda la configuración de Oracle). Puede encontrar mejoras incluso si cierra una declaración y abre una nueva, porque esto se hace a nivel de RDBMS. Este tipo de almacenamiento en caché se activa solo si las dos consultas subsiguientes (char-by-char) son iguales. Esto no se aplica a las declaraciones normales porque los parámetros forman parte de la consulta y producen diferentes cadenas SQL.

Algunos otros RDBMS pueden ser más "inteligentes", pero no creo que utilicen algoritmos complejos de coincidencia de patrones para almacenar en caché los planes de ejecución porque reduciría el rendimiento. Puede argumentar que el cálculo del plan de ejecución es solo una pequeña parte de la ejecución de la consulta. Para el caso general, estoy de acuerdo, pero ... depende. Tenga en cuenta que, por lo general, calcular un plan de ejecución puede ser una tarea costosa, ya que rdbms necesita consultar datos fuera de la memoria, como estadísticas (no solo Oracle).

Sin embargo, el argumento sobre el rango de almacenamiento en caché de los planes de ejecución a otras partes del proceso de extracción. Darle al RDBMS varias veces la misma consulta (sin profundizar en una implementación en particular) ayuda a identificar las estructuras ya calculadas a nivel JDBC (controlador) o RDBMS. Si no encuentra ninguna ventaja particular en el rendimiento ahora, no puede excluir que la mejora del rendimiento se implementará en versiones futuras / alternativas del controlador / rdbms.

Las mejoras en el rendimiento de las actualizaciones se pueden obtener utilizando declaraciones preparadas en modo por lotes, pero esta es otra historia.


Que es lo que me hace volver a la pregunta original. ¿Es este "algunos sql" PreparedStatement todavía se almacena en caché y se reutiliza bajo las cubiertas que no conozco?

Sí, al menos con Oracle. Según la base de datos Oracle® JDBC Guía del desarrollador Almacenamiento en caché de instrucciones implícito (énfasis agregado),

Cuando habilita el almacenamiento en caché de instrucciones implícito, JDBC automáticamente almacena en caché la declaración preparada o invocable cuando llama al método de close de este objeto de declaración. Las declaraciones preparadas y invocables se almacenan en caché y se recuperan utilizando métodos estándar de objeto de conexión y de declaración.

Las declaraciones simples no se almacenan en la memoria caché implícitamente, ya que la memoria caché de instrucciones implícita utiliza una cadena SQL como clave y las declaraciones simples se crean sin una cadena SQL. Por lo tanto, el almacenamiento en caché de OraclePreparedStatement implícito se aplica solo a los objetos OraclePreparedStatement y OracleCallableStatement , que se crean con una cadena SQL. No puede utilizar el almacenamiento en caché de instrucciones implícito con OracleStatement. Cuando crea una OraclePreparedStatement o OracleCallableStatement , el controlador JDBC busca automáticamente en la memoria caché una declaración coincidente .


1. PreparedStatement le permite escribir consultas dinámicas y paramétricas

Al utilizar PreparedStatement en Java, puede escribir consultas de SQL parametrizadas y enviar diferentes parámetros utilizando las mismas consultas de SQL, lo que es mucho mejor que crear consultas diferentes.

2. PreparedStatement es más rápido que Statement en Java

Uno de los principales beneficios de usar PreparedStatement es un mejor rendimiento. PreparedStatement se precompila en la base de datos y el plan de acceso también se almacena en la base de datos, lo que permite que la base de datos ejecute la consulta paramétrica escrita usando una declaración preparada mucho más rápido que la consulta normal, ya que tiene menos trabajo que hacer. Siempre debe intentar usar PreparedStatement en el código JDBC de producción para reducir la carga en la base de datos. Para obtener un beneficio de rendimiento, vale la pena destacar que solo se utiliza una versión parametrizada de consultas SQL y no con concatenación de cadenas.

3. PreparedStatement evita los ataques de inyección de SQL en Java

Lea más: http://javarevisited.blogspot.com/2012/03/why-use-preparedstatement-in-java-jdbc.html#ixzz3LejuMnVL


Respuesta corta:

PreparedStatement ayuda al rendimiento porque, por lo general, los clientes de base de datos realizan la misma consulta repetitivamente, y esto permite realizar un procesamiento previo de la consulta inicial para acelerar las siguientes consultas repetitivas .

Respuesta larga:

Según Wikipedia , el flujo de trabajo típico de usar una declaración preparada es el siguiente:

Preparar : La plantilla de sentencias es creada por la aplicación y enviada al sistema de administración de bases de datos (DBMS). Ciertos valores se dejan sin especificar, denominados parámetros, marcadores de posición o variables de enlace (etiquetados como "?" A continuación): INSERTAR EN EL PRODUCTO (nombre, precio) VALORES (?,?)

(Pre-compilación) : El DBMS analiza, compila y realiza la optimización de consultas en la plantilla de declaración, y almacena el resultado sin ejecutarlo.

Ejecutar : en un momento posterior, la aplicación suministra (o enlaza) valores para los parámetros, y el DBMS ejecuta la declaración (posiblemente devolviendo un resultado). La aplicación puede ejecutar la sentencia tantas veces como quiera con diferentes valores. En este ejemplo, podría proporcionar ''Bread'' para el primer parámetro y ''1.00'' para el segundo parámetro.

Preparar:

En JDBC, el paso "Preparar" se realiza llamando a java.sql.Connection. prepareStatement (String sql) API. Según su Javadoc:

Este método está optimizado para manejar sentencias de SQL paramétricas que se benefician de la precompilación. Si el controlador admite la precompilación, el método prepareStatement enviará la declaración a la base de datos para la precompilación. Es posible que algunos controladores no admitan la precompilación. En este caso, es posible que la declaración no se envíe a la base de datos hasta que se ejecute el objeto PreparedStatement. Esto no tiene efecto directo en los usuarios; sin embargo, sí afecta a qué métodos lanzan ciertos objetos SQLException.

Dado que la llamada a esta API puede enviar la declaración SQL a la base de datos, generalmente es una llamada costosa. Dependiendo de la implementación del controlador JDBC, si tiene la misma plantilla de sentencia de SQL, para un mejor rendimiento, es posible que tenga que evitar llamar a esta API varias veces en el lado del cliente para la misma plantilla de sentencia de SQL.

Precompilación

La plantilla de declaración enviada se compilará previamente en la base de datos y se almacenará en caché en el servidor db. La base de datos probablemente usará la conexión y la plantilla de sentencias SQL como la clave, y la consulta precompilada y el plan de consulta calculado como valor en el caché. La consulta de análisis puede necesitar validar la tabla, las columnas a consultar, por lo que podría ser una operación costosa, y el cálculo del plan de consulta también es una operación costosa.

Ejecutar:

Para las siguientes consultas de la misma plantilla de conexión y declaración SQL, la consulta precompilada y el plan de consulta se buscarán directamente desde la memoria caché por parte del servidor de base de datos sin volver a realizar el cómputo.

Conclusión:

Desde la perspectiva del rendimiento, el uso de la declaración de preparación es un proceso de dos fases:

  1. Fase 1, preparación y precompilación, se espera que esta fase se realice una vez y agregue algunos gastos generales para el rendimiento.
  2. Fase 2, ejecuciones repetidas de la misma consulta, ya que la fase 1 tiene un procesamiento previo para la consulta, si el número de consultas repetidas es lo suficientemente grande, esto puede ahorrar mucho esfuerzo de preprocesamiento para la misma consulta.

Y si desea conocer más detalles, hay algunos artículos que explican los beneficios de PrepareStatement:

  1. http://javarevisited.blogspot.com/2012/03/why-use-preparedstatement-in-java-jdbc.html
  2. http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html