Mejora de rendimiento¶
Otro aspecto importante que mide la calidad de las aplicaciones es la eficiencia con la que se consigue comunicar con el SGBD. Para optimizar la conexión es importante reconocer qué procesos pueden actuar de cuello de botella y bajo qué circunstancias o qué otras agilizan las respuestas de los SGBD.
-
En primer lugar, analizaremos la petición de conexión a un SGBD porque se trata de un proceso costoso pero inevitable que hay que considerar.
-
En segundo lugar, estudiaremos las sentencias predefinidas
PreparedStatement
, porqué su uso facilita la creación de datos clave e índices temporales de modo que sea posible anticiparse a la demanda o disponer de los datos de forma mucho más rápida.
Ciclo de vida de una conexión¶
El establecimiento de una conexión es un procedimiento bastante lento, tanto en la parte cliente como la parte servidor. En la parte cliente, DriverManager debe descubrir el controlador correcto de entre todos los que tenga que gestionar. La mayoría de veces las aplicaciones trabajarán sólo con un único controlador, pero hay que tener en cuenta que DriverManager no conoce a priori qué URL de conexión corresponde a cada controlador, y para averiguarlo envía una petición de conexión a cada controlador que tenga registrado, el controlador que no le devuelve error será el correcto.
En el lado servidor, se creará un contexto específico y se habilitarán un conjunto de recursos para cada cliente conectado. Es decir, que durante la petición de conexión del SGBD debe gastar un tiempo considerable antes de no dejar operativa la comunicación cliente-servidor.
Este elevado gasto de tiempo concentrado en el momento de la petición de conexión nos hace plantear si podemos considerar ineficiente abrir y cerrar la conexión cada vez que tengamos que ejecutar una sentencia SQL, como hemos hecho hasta ahora. Desafortunadamente no hay una única respuesta, sino que depende de la frecuencia de uso de la conexión y el número de conexiones contra un mismo SGBD coexistiendo al mismo tiempo.

Como en todo, se trata de encontrar el punto de equilibrio entre la cantidad de recursos empleados por conexión y la rentabilidad que se saca en mantenerlas abiertas.
- Si el número de clientes, y por tanto de conexiones, es bajo y la frecuencia de uso es alta, será preferible mantener las conexiones abiertas mucho tiempo.
- Por el contrario, si el número de conexiones es muy alto y el uso infrecuente, lo que será preferible será abrir y cerrar la conexión cada vez que se necesite.
Mientras tanto, habrá una multitud de casos en que la solución consistirá en mantener las conexiones abiertas, pero no permanentemente. Se puede dar un tiempo de vida a cada conexión, o bien cerrarlas después de restar inactiva una cantidad determinada de tiempo, o se puede usar el criterio de mantener un número máximo de conexiones abiertas, cerrando las más antiguas o las más inactivas cuando se sobrepase el límite.
Sentencias predefinidas¶
PreparedStatement presenta ventajas sobre su antecesor Statement cuando tengamos que trabajar con sentencias que haya que ejecutar varias veces. La razón es que cualquier sentencia SQL, cuando se envía el SGBD será compilada antes de ser ejecutada. Usando un objeto Statement
, cada vez que hacemos una ejecución de una sentencia, ya sea vía executeUpdate o bien vía executeQuery
, el SGBD la compilará, ya que le llegará en forma de cadena de caracteres.
En cambio, al PreparedStament
la sentencia nunca varía y por lo tanto se puede compilar y almacenar dentro del mismo objeto, por lo que las siguientes veces que se ejecute no habrá que compilarla. Esto reducirá sensiblemente el tiempo de ejecución. La parametrización, además, ayuda a crear sentencias muy genéricas que se puedan reutilizar fácilmente.
En algunos sistemas gestores, además, usar PreparedStatement
puede llegar a suponer más ventajas, ya que utilizan la secuencia de bytes de la sentencia para detectar si se trata de una sentencia nueva o ya se ha servido con anterioridad. De esta manera se propicia que el sistema almacene las respuestas en la caché, de manera que se puedan entregar de forma más rápida.
Quote
This is a fact, a rule, a law -- use prepared statements EVERYWHERE. Use STATEMENTS almost no where.
Casos de uso¶
Statement acepta cadenas como consultas SQL. Por lo tanto, el código se vuelve menos legible cuando concatenamos cadenas SQL:
public void insert(PersonEntity personEntity) {
String query = "INSERT INTO persons(id, name, age, email) VALUES("
+ personEntity.getId() + ", '"
+ personEntity.getName() + "', "
+ personEntity.getAge() + ", '"
+ personEntity.getEmail() + "')";
Statement statement = connection.createStatement();
statement.executeUpdate(query);
}
Es vulnerable a la inyección de SQL.
public void check(String name) {
String query = "SELECT * FROM users WHERE name = '" + name + "'";
Statement statement = connection.createStatement();
statement.executeUpdate(query);
}
Alicia'; DROP TABLE usuarios; SELECT * FROM datos WHERE nombre LIKE '%