Tips pa mejores QUERYS

que tal amigos jav-eros, después de mucho; entro a postear en mi blog, no creo poder hablar de cosas de las cuales no se haya hablado ya :(. Por el momento me encuentro atado trabajando con PHP y JavaScript (así que si tienen una duda, pues aquí estamos, patterns, ajax, AFO's, DOM, HTML) :S me está gustando, pero mi alma le pertenece a Java :P, por lo tanto he retomado el camino de la "fuerza" y empezare de nuevo con java, mi primer aporte creo que es muy bueno son unos tips de SQL (espero les agraden, se acepta toda clase de comentarios y retroalimentación)

Unos cuantos tips de cómo hacer unos query's mas rápidos:

1. Usar conexiones a bases de datos que sean persistentes, esto para evitar sobrecarga. Algo más o menos como los Singleton's.

2. Checar que todas nuestras tablas tengan PRIMARY KEYs y que si hay FOREING KEYs estas tengan una cardinalidad alta (muchos registros con la misma FKEY). Bueno siempre habrá excepciones como por ejemplo "sexo" (ha que bueno) es una columna que tiene baja cardinalidad y eso no hay problema, pero un "user_id" es un buen candidato para una cardinalidad alta.

3. Usa menos memoria RAM declarando tus columnas tan grandes como vas a utilizar (tener un "User_key" tipo varchar de 2^31-1 bytes en el caso de sqlserver no es muy agradable para la RAM cuando solo van a utilizar 10 caracteres);

4. Todas las referencias entre las distintas tablas deben de hacerse con índices (esto quiere decir que los campos que van a relacionarse deben de tener los mismos tipos de campos, y las mismas características: tamaño y validaciones, esto ayuda a que el engine de nuestro DBM hará las correspondencias entre columnas mas rápido, que si solo los ponemos del mismo tipo). También hay que checar que los campos que ocupemos recurrentemente en búsquedas tengan índices, pero no hay que añadir demasiados

5. Evita hacer muchos loops al crear querys (evita crear muchos querys), aunque no lo creas esto le pesa mucho a la maquina, en promedio la realización de un query toma entre 20 -700 ms esto no es mucho, pero por ejemplo si tenemos un loop FOR que realiza un query que le toma a la maquina 30 ms (y esto sin contar que entre más registros va a ir creciendo el tiempo) y este for realiza 5000 querys tomaría unos 150 s en cambio si se crea un query más complejo que obtenga un resultado global y después se les da un manejo a nivel de código esto siempre sera mucho más rápido es decir un query que tarde 150 ms (para este ejemplo) y un procesamiento a nivel de código con loop FOR sera más factible en recorrer los registros tardaría unos 500 ms en promedio 600-700 ms comparados con los 150000 ms pues creo que se ve la diferencia. Ahora si por el contrario en loop lo pueden meter en un IN esto sería de mucha ayuda el server se los agradecerá ej. Select * from tabla nombre_del_campo IN (valor1, valor2);

6. Indexar indexar ... muchas veces esto no lo hacemos, he inclusive en sistemas grandes que no voy a mencionar se les ha pasado este pequeñísimo detalle :S, todas las referencias entre los distintas tablas normalmente deben de ser indexados (tener el mismo tipo de campos entre los dos índices es mucho mejor y más rápido, ya que el DBMS no se tendrá que ocupar por estar yendo a comparar los tipos de datos, tratando de darles una conexión al ser de distintos tipos, créame ha pasado :( que intentan conectar FK int con varchar :S). También el tener indexados los campos que se ocuparan en una búsqueda resulta más práctico para el procesador de el DBMS (estos son buscados con alta prioridad por un WHERE, ORDER BY o GROUP BY) bueno hay que tener los índices necesarios no demasiados, esto también es peligroso (cuantos, mmm es necesario un análisis de la DB, para una pequeña de unas 5 tablas quizás una indexacion de 2-3 campos por tabla es suficiente, pero esto varia; aunque nunca he visto una tabla con más de 5 índices por tabla).

7. Algo que no está de más es correr un ANALYZE TABLE (myisamchk – es bueno aunque en línea de comandos) sobre las tablas después de haber hecho la carga de datos, esto ayuda a optimizar mejor los querys.

8. Ha ya me dio sueñito… jajaja espero les agrade los seguiré molestando con mis publicaciones, por ahora PAUSA, espero todo tipo de criticas serán bienvenidas. =D

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

puntos 1 y 6

Imagen de ezamudio

Solamente quiero mencionar algo respecto a los puntos 1 y 6:
1. Singletons para conexiones a base de datos? Es decir tener una conexión a la base de datos y mantenerla viva todo el tiempo y accesible para toda la aplicación? qué pasa cuando dos hilos quieren usar la conexión de manera concurrente? Para esto existen soluciones como Apache DBCP y C3P0, que son pools de conexiones a base de datos los cuales nada más configuras con el mínimo/máximo de conexiones, tiempo máximo de espera antes de crear nuevas conexiones, etc y tu aplicación lo ve como un DataSource al que se le piden conexiones (ese sí lo puedes poner como singleton). No hay que inventar el hilo negro...

6. Así como es malo no tener índices, puede ser malo también tener demasiados índices. Esto ya es bronca de un DBA, no es un programador Java. Pero ya que estamos tratando el tema... una tabla con varios índices hace que los INSERTs sean más lentos porque se tienen que actualizar todos los índices. He visto que una tabla con varios millones de registros y 10 índices puede causar que un INSERT tarde más de 30 segundos (y al mismo tiempo se están contestando queries sobre dicha tabla con un tiempo rapidísimo, pero pobre del proceso que está esperando a que termine su INSERT). Ahí la solución es revisar los índices que realmente se están usando más y ver si se pueden eliminar los menos utilizados, eso ya solamente puede ser sobre el sistema en producción. Y entonces se pueden tirar algunos índices y crear otros distintos, de manera que al final en vez de 10, tengamos tal vez 4 o 5 que se usen en todos los casos.

Conexiones persistentes a base de datos

1. Singletons para conexiones a base de datos? Es decir tener una conexión a la base de datos y mantenerla viva todo el tiempo y accesible para toda la aplicación? qué pasa cuando dos hilos quieren usar la conexión de manera concurrente? Para esto existen soluciones como Apache DBCP y C3P0, que son pools de conexiones a base de datos los cuales nada más configuras con el mínimo/máximo de conexiones, tiempo máximo de espera antes de crear nuevas conexiones, etc y tu aplicación lo ve como un DataSource al que se le piden conexiones (ese sí lo puedes poner como singleton)

Creo que hay una confusión. El uso de conexiones persistentes que menciona Neftali es una característica que se espera que proporcionen los "pools" de conexiones, al menos los más avanzados como los de WebLogic o WebSphere.

Del manual "Configuring and Managing WebLogic JDBC", Capítulo 3 "Tunning Data Source Connection Pool Options":

When Pinned-To-Thread is enabled, WebLogic Server pins a database connection from the data source to an execution thread the first time an application uses the thread to reserve a connection. When the application finishes using the connection and calls connection.close(), which otherwise returns the connection to the data source, WebLogic Server keeps the connection with the execute thread and does not return it to the data source. When an application subsequently requests a connection using the same execute thread, WebLogic Server provides the connection already reserved by the thread. There is no locking contention on the data source that occurs when multiple threads attempt to reserve a connection at the same time and there is no contention for threads that attempt to reserve the same connection from a limited number of database connections

Del manual "WebSphere Application Server documentation", Learn about Websphere applications, Data access resources, Connection management architecture

The possible benefits of unshared connections

* Your application always maintains a direct link with a physical connection (managed connection).
* The connection always has a one-to-one relationship between the connection handle and the managed connection.
* In most cases, the connection does not close until the application closes it.
* You can use a cached unshared connection handle across multiple transactions.
* The connection can have a performance advantage in some cached handle situations. Because unshared connections do not have the overhead of moving connection handles off managed connections at the end of the transaction, there is less overhead in using a cached unshared connection.

Lo que creo que no fue muy afortunada fue la comparación con un singleton ;-) Ojalá Neftalí nos compartiera la o las fuentes de tan buenas heurísticas.

Saludos

Javier Castañón

base de datos

hola.. tengo un problema con mi base de datos..!! tngo un metodo q recupera los apellidos d mi base de datos a traves de un ResultSet rs por ejmplo si tngo apellido lopez garcia y lopez timana ala hora q yo ingreso solo lopez quiero q se me cargue a un vector los 2 apellidos con su respectivo nombre el problema esta cuando recupera el nombre del primer apellido ala ora d cargar el siguiente apellido el resultset rs se cierra "java.sql.SQLException: ResultSet is closed" m sale ese mensaje alguna ayuda de antemano seria les agredeceria.. saludos.. Max
"