 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Dom 24 Ago, 2003 1:27 pm Asunto: Consulta SQL tarda mucho |
|
|
En esta aplicación el usuario selecciona dos fechas y tras ello empieza a ejecutarse la sentencia sql que se encarga de seleccionar los valores de todos los registros comprendidos entre las dos fechas seleccionadas.
Al principio todo iba como la seda pero a medida que los registros de la tabla aumentan la consulta se haca más y más lenta , estoy hablando de una tabla que en un més puede llegar a incrementarse en unos 5000 registros.
Me gustaría encontrar el modo de que esa consulta fuese más rápida. Gracias. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Dom 24 Ago, 2003 3:05 pm Asunto: |
|
|
Imagino que dentro del Select irán solamente los campos que vas a mostrar en la consulta, me refiero que no será un SELECT * FROM .... ?
Tienes establecidos algun indice para el campo fecha ? |
|
| Volver arriba |
|
 |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Dom 24 Ago, 2003 5:42 pm Asunto: |
|
|
efectivamente tenía un SELECT * FROM y ya lo he corregido, ahora sólo he puesto el campo que me interesa mostrar: SELECT Cantidad FROM Cuentas WHERE FECHA>=:parametro1 AND FECHA<=:parametro2
Pero aún así es igual de lento , por cierto NO tengo ningún indice definido para el campo fecha ya que tengo muy poca experiencia en esto y no se muy bien para que sirven. Si puedes seguir ayudándome te lo agradeceré .
Saludos. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Dom 24 Ago, 2003 6:22 pm Asunto: |
|
|
Los indices tienen algunas mejoras y también algunos incovenientes, te sugiero que amplies tu información por internet o con algun libro hay mucho al respecto.
Basicamente los indices sirven para agilizar la consulta de tuplas por ciertos campos que no son claves primarias, pero que se suelen utilizar a menudo con motivo de la consulta. Digo que no son claves primarias, porque estás ya se encuentran indexadas.
Logicamente el tener indices va a engordar un poquito tu Base de datos y también va a perjudicar, que las insercciones, modificaciones o borrados, sean un poquitín más lentos. Pero quizás en tu caso pueda ser intersante es cuestión de definir el indice, lanzar la consulta y estudiar el tiempo de esta. Quitar el indice, lanzar de nuevo la misma consulta y ver si tarda lo mismo o más. Es decir, si va a tardar menos cuando el indice existe.
En tu caso fijate que estás usando las fechas para realizar la consulta, al tener el indice creado sobre fechas, las consultas que lanzes sobre este campo serán más rapidas, el tener el campo ya indexado. Comprendes ?
Aun así siempre que uses consultas debes solo pedir los campos que te interesen, imaginate que la aplicación que estes haciendo con esa consulta que tu has dicho SELECT * FROM ... WHERE fecha ....
la lanzas en una Red, imaginate la de datos que se tiene que traer frente a un SELECT cantidad FROM .... WHERE fecha.... que solo se trae un campo. Si cada registro tuviera 500 bytes y de esos 500 bytes el campo cantidad supone 2 bytes y tienes 5000 registros en la tabla, pues por pocas cuentas que hagas, te darás cuenta de que traerse 10.000 bytes es decir aprox. 10KB, no es lo mismo que traerse 2.500.000 bytes = aprox. 2.500 KB = aprox. 2,5 MB ojo 2,5 MEGABYTES ya ves!! ahí es nada, imaginate si en vez de 5000 registros son 20.000 registros, ya hubieras saturado probablemetne el ancho de banda de la red para un simple consulta de 200 KB. Comprendes esta notable cuestion, no ? Te sugiero siempre que en tus consultas SELECT, intentes averiguar que campos te hacen falta y desechar los otros, así mejoraras todo, tanto el rendimiento del SGBD (Servidor BD) como el trafico de datos por la red, o entre el servidor y tu programa, Algo que afectará también por supuesto a los tiempos de espera de consulta y a la latencia de tu programa.
Te paso algunos enlaces que seguro que te lo aclaran mejor que yo. Los he sacado del google.
http://www.desarrolloweb.com/articulos/271.php?manual=9
http://www.programacion.com/tutorial/sql/19/#sql_optimizar_indices
Ciao. |
|
| Volver arriba |
|
 |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Dom 24 Ago, 2003 7:12 pm Asunto: |
|
|
Muchísimas gracias XyVy por tu colaboración, decirte que ya lo tengo solucionado, a ver si soy capaz de explicarme:
Resulta que tras la consulta tenía que ir sumando los registros de los campos obtenidos y meter el resultado en un Edit, pues bien lo que hacía en lugar de coger los valores del Query de la consulta los cogía de un TTable enlazado a la misma tabla a través de una sentencia for() y supongo que al ser el recorrido por el TTable y no por el TQuery el for se comía todos los campos y registros en busca de la condición y creo que es eso lo que me provocaba el retraso. He hecho que el for me recorra el resultado del Query ¡ Y NO VEAS QUE CAMBIO ! , en menos de dos segundos ha sacado la información que le he pedido de entre mas de 6000 registros. Creo que con esto ya me doy por satisfecho, y gracias otra vez XyVy.
Saludos. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Dom 24 Ago, 2003 7:30 pm Asunto: |
|
|
Hombre jajaja!!! veo que tenías un fallo grave.
Si usas el TQuery para hacer una consulta luego debes recorrer el TQuery. Es decir.
| Código: |
TQuery->Clear();
TQuery->SQL->Add("SELECT bla, blah FROM blah, blah WHERE blah";
TQuery->Prepare();
TQuery->Open();
TQuery->First();
while (!TQuery->Eof) {
// lee_campos y hace operaciones con el registro del TQuery
...
// Pasa al siguiente registro
TQuery->Next();
}
TQuery->Close();
|
Ese sería el modo de trabajo de un recorrido por el TQuery, lo que no puedes hacer es el ejecutar el TQuery y recorrer un TTable, porque no es lo mismo.
Por cierto una pregunta si tu for (es una duda que tengo) si tu for lo que haces es sumar las cantidades de una tabla entre dos fechas. Con una consulta lo puedes hacer también en menos de 1 segundo (Bueno esto es un decir, pero está claro que más rapido que un for).
| Código: |
SELECT SUM(CANTIDAD) AS CANTIDAD
FROM ....
WHERE fecha....
|
El resultado será una tupla con un campo llamado (pongo el AS CANTIDAD porque sino se llamaría SUM o algo así) CANTIDAD con la suma de todas las cantidades de esa tabla comprendida entre las fechas que pusieras. Es eso lo que quieres hacer ? |
|
| Volver arriba |
|
 |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Dom 24 Ago, 2003 9:05 pm Asunto: |
|
|
Era exacatamento eso, diste en el clavo , con lo del SUM.
Ahora lo que tengo que intentar es cómo demonios paso el resultado de esa suma a un Edit, no tiene pinta de ser difícil pero ahora tengo que ir a cenar, y si tengo tiempo luego lo intento, ya te diré cosas... ¡AH! y gracias otra vez fenómeno. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Dom 24 Ago, 2003 9:26 pm Asunto: |
|
|
Vamos a ver, primero de fenomeno nada, se intenta ayudar en lo que se puedo yo hago más preguntas, que preguntas ayudo a resolver, pero bueno como digo se hace lo que se puede.
Por el tema en concreto, pues como imagino que estas en Builder C++, es lo más sencillo del mundo. Mira imaginemos que eso que te he dicho es realmente lo que quieres conseguir pues se haría algo así:
| Código: |
TQuery->Clear(); // Por si lo hemos utilizado en alguna query anterior
TQuery->SQL->Add("SELECT SUM(CANTIDAD) AS CANTIDAD");
TQuery->SQL->Add("FROM CUENTAS");
TQuery->SQL->Add("WHERE FECHA>=" + fecha_inferior + " AND FECHA<=" + fecha_superior);
TQuery->Prepare(); // Esto prepara la consulta
TQuery->Open(); // Esto la ejecuta
TQuery->First();
// Ahora meteremos el campo cantidad en el edit
Edit1->Text=IntToStr(TQuery->FieldByName("CANTIDAD")->AsInteger);
TQuery->Close();
|
También podrías utilizar la clasula BETWEEN, es decir entre dos cosas, muy util para las fechas o cuando tienes dos limites, es decier uno inferior y otro superior. Ejemplo con el Between:
| Código: |
TQuery->Clear(); // Por si lo hemos utilizado en alguna query anterior
TQuery->SQL->Add("SELECT SUM(CANTIDAD) AS CANTIDAD");
TQuery->SQL->Add("FROM CUENTAS");
TQuery->SQL->Add("WHERE FECHA BETWEEN " + fecha_inferior + " AND " + fecha_superior);
TQuery->Prepare(); // Esto prepara la consulta
TQuery->Open(); // Esto la ejecuta
TQuery->First();
// Ahora meteremos el campo cantidad en el edit
Edit1->Text=IntToStr(TQuery->FieldByName("CANTIDAD")->AsInteger);
TQuery->Close();
|
Como ves no es dificil. Muy sencillito. Espero que sea eso lo que pretendes hacer, si es así, pues genial ya sabes como hacerlo para la proxima vez.
SUM es una función agregada de SQL que devuelve la SUMA de cierto campo en todos los registros del SELECT. Al igual que SUM tienes otras muy utiles como:
SUM(nombre_campo)
Devuelve la suma del campo "nombre_campo" para todos los registros del select.
MAX(nombre_campo)
Devuelve el maximo valor para ese campo entre todos los registros del selectl.
MIN(nombre_campo)
Devuelve el minimo valor para ese campo entre todos los registros del select.
Tienes algunos más pero esos son los más utiles, piensa que cuanto más carges en el servidor de BD (SGBD) las cosas, más sencillo quedará tu programa, correrá en la mayor parte de los casos, más eficientemente y tardará menos tiempo en devolver el resultado esperado. Así que cuanto más te acostumbres a usar las consultas mejor, cuanto más concretas sean todavía mejor.
Ciao. |
|
| Volver arriba |
|
 |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Lun 25 Ago, 2003 7:47 pm Asunto: |
|
|
Fantástico XyVy, ahora si que va rápido saca los resultados en menos de un segundo.
Ahora tengo otro pequeño inconveniente: una vez sacados estos resultados los lanzo a un quickreport en el cual tengo un QRMemo que reelleno utilizando de nuevo un for() sobre los resultados de la consulta. Ahora la lentitud ya no está en la consulta sino en la previsualización del reporte antes de imprimirlo.
¿alguna idea?, gracias. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
XyVy Master


Registrado: 25 Ago 2002Mensajes: 557Ubicación: Murcia (España)
|
Publicado: Lun 25 Ago, 2003 7:58 pm Asunto: |
|
|
Mira sobre QuickReport si que me pillas, ahí no tengo ni papa la verdad, pero te digo una cosa, en el momento que la BD ya no es preocupante, pasa a ser preocupante otra cosa, esto me recuerda la famosa Ley de Amdahl muy preocupante en la mejora de la arquitectura de los computadores.
Y digo yo, me parece que además del TQuery estas haciendo otro acceso a datos para tener más datos no ? No podrás juntarlo todo en una unica consulta ?
Si lo que quieres por ejemplo imaginate son cantidades por cliente desde esta fecha a este otra, y además en el QuickReport usas datos del cliente, todo eso se puede procesar como una unica consulta. Dime que quieres hacer concretamente para ver que se puede hacer. Ciao. |
|
| Volver arriba |
|
 |
Alfredo Invitado
|
Publicado: Lun 25 Ago, 2003 9:37 pm Asunto: QR |
|
|
| Hola, por que necesitas un for para llenar el QR? usa un QRDBtext y enlazalo a la Query o Tabla que estes usando, es igual que con los DBEdits. |
|
| Volver arriba |
|
 |
Alfredo Invitado
|
Publicado: Lun 25 Ago, 2003 9:37 pm Asunto: QR |
|
|
| Hola, por que necesitas un for para llenar el QR? usa un QRDBtext y enlazalo a la Query o Tabla que estes usando, es igual que con los DBEdits. |
|
| Volver arriba |
|
 |
Angel Master


Registrado: 15 Abr 2003Mensajes: 2311Ubicación: Toledo (España)
|
Publicado: Mar 26 Ago, 2003 9:06 am Asunto: |
|
|
No te hace falta ningún tipo de bucle para rellenar un informe con QR. Simplemenete, lo que tienes que hacer es poner una banda del tipo rbDetail. Teniendo bien diseñado el informe no hace falta ningún tipo de bucle ya que el sólo se encarga de gestionar la distribución del mismo.
En http://www-corot.obspm.fr/COROT-ETC/Files/QReport.pdf tienes un manual en formato PDF sobre como usar QR 3; aunque está en inglés, es fácil de entender (hasta yo que no tengo NPI lo entiendo ) _________________ Un saludo
Necesitamos tu ayuda: Envía AI al 27595 (Coste 1,20 euros + IVA) |
|
| Volver arriba |
|
 |
Tugui Master


Registrado: 09 Nov 2002Mensajes: 663
|
Publicado: Mar 26 Ago, 2003 2:56 pm Asunto: |
|
|
Gracias Angel, miraré ese link en cuanto tenga un poco de tiempo, de momento deciros que lo he probado con un DBEdit pero sólo me muestra el primer registro del query cuando lo que quiero es que me los muestre todos en forma de columna al estilo Memo, también he probado con el DBRichEdit pero ese ha ido peor ( no me muestra nada de nada) .
Seguiré intentándolo . Gracias a todos. _________________ ¡ADELANTE CON ESTE SUPER FORO! |
|
| Volver arriba |
|
 |
Marky Master

Registrado: 28 Dic 2002Mensajes: 251Ubicación: Las Rozas - Madrid (España)
|
Publicado: Mar 26 Ago, 2003 5:04 pm Asunto: |
|
|
| ¿Estás seguro de que has ajustado las propiedad Dataset del QRDBText y del QReport? y.... ¿has puesto a rbDetail la propiedad BandType de tu QRBand? |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|