Ir al contenido


Foto

Optimizar filtro dataset


  • Por favor identifícate para responder
15 respuestas en este tema

#1 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 05 diciembre 2014 - 04:27

Hola amigos, tengo una aplicacion que muestra los datos de una consulta mysql en un dbgrid
y un editi para que el usuario filtre una busqueda, bueno para filtrar utilizo este codigo


delphi
  1.   // en el onChange del edit_filtro
  2.   Dataset.Filter := 'descripcion LIKE '+#39+'*'+ed_filtro.text+'*'+#39;
  3.   Dataset.FilterOptions := [foCaseInsensitive];
  4.   Dataset.Filtered := (ed_filtro.Text <> '');


Todo va muy bien pero cuando son miles de registros entonces me traba la aplicacion
y tengo que esperar hasta que responda, puden ayudarme a como agilizar esto.
Saludos.
  • 0

#2 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 05 diciembre 2014 - 04:37

Es pésima idea utilizar el evento onChange cuando hay muchos registros, deberías colocarlo en el evento ONKeyPress.

Si aún persistes en usar el evento OnChange, entonces puedes ayudarte de un TTimer, para que el filtro no se ejecute con cada letra tecleada si no al cabo de cierto tiempo.

Si te atoras con la implementación con el TTimer avisas para ayudarte.

Saludos.
  • 0

#3 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 05 diciembre 2014 - 04:41

Entonces en con el timer y en el evento onKeyPress aun si colocaran una letra ¿No sucederia lo mismo, que se trabara?
  • 0

#4 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 05 diciembre 2014 - 04:53

Entonces en con el timer y en el evento onKeyPress aun si colocaran una letra ¿No sucederia lo mismo, que se trabara?


A ver, lo que pasa es que en el evento ONChange por cada letra que tecleas se ejecuta el procedimiento, si lo colocas en el evento OnKeyPress, este recibe una variable (key) de tipo char como parámetro, en la cual puedes especificar con que tecla dispare el procedimiento, entonces puedes escribir 3, 4, 5 ... n.. letras y luego pulsar por ejemplo la tecla ENTER y ejecutar solo una vez el procedimiento (en vez de ejecutarse n letras) y por supuesto el rendimiento debe mejorar.



delphi
  1. procedure TFom1.EditFiltroKeyPress(Sender: TObject; var Key: Char);
  2. begin
  3.   if key = # 13 then //#13  es la tecla ENTER
  4.     begin
  5.         Dataset.Filter := 'descripcion LIKE '+#39+'*'+ed_filtro.text+'*'+#39;
  6.         Dataset.FilterOptions := [foCaseInsensitive];
  7.         Dataset.Filtered := (ed_filtro.Text <> '');
  8.     end;
  9. end;



Lo mismo harías con el Timer, evitar que el procedimiento se dispare tantas veces y por lo tanto debe mejorar el rendimiento.

Saludos.
  • 0

#5 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 05 diciembre 2014 - 05:02

Si, el problema es que cuando es onKeyPress la busqueda se hace hasta que presiones "Enter"
y queria ver si se pude optimizar que el usuario al ir escribiendo en el editi se vaya haciendo la busqueda
aun asi ponga una letra o una palabra completa, si no hay de otra tendre que usar el onKeyPress
  • 0

#6 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 05 diciembre 2014 - 08:25

Mejor no usar filtros. Mejor no usar incrementales. Los filtros no son buenos por que traen todos los datos y luego los pone a prueba.
Usa el cuadro de edicion para ingresar parametro de consulta. Utiliza consultas. Para eso es sql.

  • 0

#7 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 05 diciembre 2014 - 08:51

Mejor no usar filtros. Mejor no usar incrementales. Los filtros no son buenos por que traen todos los datos y luego los pone a prueba.
Usa el cuadro de edicion para ingresar parametro de consulta. Utiliza consultas. Para eso es sql.


Depende, depende, depende ...., en el caso que nos ocupa, el que sea un filtro o una consulta no es el verdadero problema, el lío es la cantidad de veces que se lanza el filtro o la consulta.

Si sigues usando el evento OnChange para lanzar consultas a un servidor vas a tener incluso un rendimiento menor que si aplicaras filtros en local.

Un cordial saludo.
  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.301 mensajes
  • LocationArgentina

Escrito 06 diciembre 2014 - 08:28

¿Que necesidad tiene el usuario de recibir miles de registros?
Si es posible ya traerle los datos pre-filtrados mejor.

Todos los que han intervenido en el hilo bien que saben que los Table no son una buena opción cuando se tienen tablas con muchos registros. Siempre en lo posible hay que trabajar con Query que traigan los datos esenciales.

Esto ya de pleno ayuda enormemente. Por el lado del rendimiento, en lugar de traerse todos los registros se extraen sólo los que en verdad necesita el cliente. Por el lado del cliente, se sentirá a gusto en vez de recibir 1000, ahora tendrá apenas unos 200 o 300. Todos ganan.

Ahora esto no impide que se necesite filtrar sobre algo ya filtrado. Los componentes Query, como todo DataSet cuenta con la propiedad Filters. La diferencia estará que en lugar de aplicar el filtro sobre la totalidad de una tabla, lo hará sobre una consulta que ya de entrada puede venir filtrada.

Mi consejo para edorantes que que migre al pensamiento Query y piense de que formas puede traerle al cliente los datos que el cliente solicite en lugar de traer cada dos por tres todos. Preguntas que debiera hacerse edorantes: ¿Es necesario traer la totalidad de los registros? ¿Cuál es la idea u objetivo de aplicar este filtro? ¿Sólo buscar algo en particular? ¿Trabajar con ese registro en particular?

Saludos,
  • 0

#9 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 06 diciembre 2014 - 09:06


Todos los que han intervenido en el hilo bien que saben que los Table no son una buena opción cuando se tienen tablas con muchos registros.


Sin el ánimo de entrar en discusiones baladíes, el compañero Edorantes no habla de un@ Table, habla de una consulta (Query).

Lo de los filtros es algo muy relativo y como dice Egostar, depende, depende, depende .... Solo basta mirar por ejemplo,  que son justo filtros los que usan muchos componentes de acceso a datos descendientes de TDataset para manejar las relaciones Maestro - Detalles, y estos  pueden incluir desde 0 registros hasta miles, solo por citar un ejemplo.

El rendimiento en las consultas que involucran muchos registros  pasa más por detalles como el concepto de  paginación (Fetch records), traer registros por demanda ( Fetch On Demand) y la sincronización con componentes  visuales (dbGrid), todo depende de la implementación de cada componente.

Ahora bien para no salirnos de la pregunta del interesado, vuelvo y repito el problema principal de rendimiento no se debe a que sea  un filtro o una consulta, se debe a la cantidad de veces que se tiene que ejecutar el procedimiento (cualquiera que sea) en el evento OnChange de un TEdit; supongan que en vez de un filtro hace una consulta que satisfaga lo que quería hallar en el filtro y le pasa como parámetro el contenido del TEdit e intenta ejecutarla en el evento ONChange de este, si la consulta devuelve muchos registros, pues la aplicación vuelve y se cuelga porque tiene que ejecutarse tantas veces como letras escriba; por lo tanto para dar respuesta concreta a la pregunta sugiero que use el evento ONKeyPress para ejecutar un filtro o una consulta.

Un cordial saludo,


  • 0

#10 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 06 diciembre 2014 - 09:37

Bueno en los anteriores casos que hemos trabajado con el filtro no nos habia dado problemas con pocos registros
y se venia trabajando bien.
La idea era que si el cliente requeria o no se acordaba de un registo le dabamos la opcion de mostrale todos
en un grid ligado a un dataset y ponerle un filtro mediante el evento onChange del filtro conforme iba escribiendo se haria el filtrado
usando la propiedad filter del dataset
pero como ahora los registros sobrepasan los 30,000 eso hace que la aplicacion se congele.
Por lo que ustedes comentan la opcion que veo mas viable es de utilizar el onKeyPress y hacer el
filtrado por palabra
  • 0

#11 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 06 diciembre 2014 - 09:47

Yo hace mucho dejé de usar los filtros integrados en los datasets precisamente por esos inconvenientes. Ahora prefiero ejecutar consultas  y que sea la base de datos la que se encargue de la optimización.  (y)  (y)
  • 0

#12 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 06 diciembre 2014 - 10:16

He estado ralizando pruebas y me di cuenta que se optimizo un poco al cambiar el dataset
tenia un readonly dataset  y lo cambie por un query dataset y por lo menos ahora la aplicacion
no se congela, hace la busqueda pero tarda como 1 segundo en mostrar los datos
pero aun asi si yo tengo un equipo con buenos requerimiento esto tardaria mas en equipos
viejos
  • 0

#13 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 06 diciembre 2014 - 10:20

Yo hace mucho dejé de usar los filtros integrados en los datasets precisamente por esos inconvenientes. Ahora prefiero ejecutar consultas  y que sea la base de datos la que se encargue de la optimización.  (y)  (y)


Yo también. Lo único que le aconsejo  al amigo EDorantes es que no utilice el evento ONChange del TEDit para ejecutar sus consultas, que en su defecto use el evento ONKeyPress.

Un cordial saludo.
  • 0

#14 edorantes

edorantes

    Advanced Member

  • Miembros
  • PipPipPip
  • 78 mensajes

Escrito 06 diciembre 2014 - 10:27

Si lo se, he optado por utilizar el onKeyPress para evitar problemas y asi realizar una busqueda por palabra bueno gracias a todos por tomarse un
tiempo para responderme.
Bendiciones.
  • 0

#15 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.301 mensajes
  • LocationArgentina

Escrito 06 diciembre 2014 - 11:35

Sin el ánimo de entrar en discusiones baladíes, el compañero Edorantes no habla de un@ Table, habla de una consulta (Query).

Tuve que volver a leer el hilo para comprobarlo. ¡Hubiera jurado haber leído que estaba usando Tables!  :o Vaya que ando mal... tengo el cerebro quemado con mis proyectos. Mejor me voy a jugar a un videojuego y descanso la cabeza...

Mis diculpas si alguien se ha sentido ofendido.

Lo de los filtros es algo muy relativo y como dice Egostar, depende, depende, depende .... Solo basta mirar por ejemplo,  que son justo filtros los que usan muchos componentes de acceso a datos descendientes de TDataset para manejar las relaciones Maestro - Detalles, y estos  pueden incluir desde 0 registros hasta miles, solo por citar un ejemplo.

El rendimiento en las consultas que involucran muchos registros  pasa más por detalles como el concepto de  paginación (Fetch records), traer registros por demanda ( Fetch On Demand) y la sincronización con componentes  visuales (dbGrid), todo depende de la implementación de cada componente.

Ahora bien para no salirnos de la pregunta del interesado, vuelvo y repito el problema principal de rendimiento no se debe a que sea  un filtro o una consulta, se debe a la cantidad de veces que se tiene que ejecutar el procedimiento (cualquiera que sea) en el evento OnChange de un TEdit; supongan que en vez de un filtro hace una consulta que satisfaga lo que quería hallar en el filtro y le pasa como parámetro el contenido del TEdit e intenta ejecutarla en el evento ONChange de este, si la consulta devuelve muchos registros, pues la aplicación vuelve y se cuelga porque tiene que ejecutarse tantas veces como letras escriba; por lo tanto para dar respuesta concreta a la pregunta sugiero que use el evento ONKeyPress para ejecutar un filtro o una consulta.

Un cordial saludo,

Pues si, son varias cosas. Pero lo fundamental es como dices, la veces que se debe ejecutar la consulta. Para tablas muy grandes las búsquedas incrementables no son del todo buena idea. Las opciones que se han propuesto ayudan mucho a mitigar, o a reducir estos efectos. Pero hay otros enfoques que directamente atacan a estos síntomas.

Bueno en los anteriores casos que hemos trabajado con el filtro no nos habia dado problemas con pocos registros
y se venia trabajando bien.
La idea era que si el cliente requeria o no se acordaba de un registo le dabamos la opcion de mostrale todos
en un grid ligado a un dataset y ponerle un filtro mediante el evento onChange del filtro conforme iba escribiendo se haria el filtrado
usando la propiedad filter del dataset
pero como ahora los registros sobrepasan los 30,000 eso hace que la aplicacion se congele.
Por lo que ustedes comentan la opcion que veo mas viable es de utilizar el onKeyPress y hacer el
filtrado por palabra

Esto que comentas es un caso clásico: Se prepara un sistema, y no se termina de ver el alcance del crecimiento de una base de datos. Error típico de "bueno, si no lo recuerda le mostramos todo".
Si para ya 1000 registros es molesto darle al usuario... ¡imaginte los 30mil que dices!

Allí hay un defecto de diseño. ¡No le muestres todos si son miles de miles! Hazlo más simple: solo pon los campos por los cuales buscar, y que luego el sistema ejecute consultas. No filtres, ¡Que se ejecuten consultas de tipo búsquedas más restrictivas!

O bien, en lugar de mostrar todos. Muestra los x más usados/populares/consultados/etc. Si no está allí recién buscar. De todas formas trata de hacer que la búsqueda sea lo más directa posible de modo que los resultados lleven a pocos registros.
Piensa que es frustante para un usuario que una búsqueda le devuelva 1000 registros, cuando el sólo está esperando 1 o 10. Cuanto más directo se sea para llegar al resultado mejor será.

Saludos,
  • 0

#16 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 06 diciembre 2014 - 05:22

Bien lo explican Delphius y Poliburro.
Hasta el punto que las nuevas tecnologías descartan los filtros o los relegan a un segundo plano. No quiero decir bobadas sin saber, pero creo que eso existe desde la época de BDE (Borland Database Engine) y quedó, como caso de compatibilidad. Y hasta me imagino que el tema nació en el ambiente de xBase.
El asunto de mi brevedad es que respondí desde el teléfono de mi esposa  :grin:  ¡ese teclado en pantalla! 8o|

Pero, edorantes, para ayudarte a simular una búsqueda incremental te sugiero uses este truco:
Captura el evento OnKeyPress como lo enseña Wilson.
En el método, arma un parámetro y con éste, la consulta y solicita solo la cantidad que se desplegará en pantalla (serán a lo sumo 20 o 30) con FIRST nn.
Entre tecla y tecla (caracteres) deberás reabrir la consulta para refrescar los datos.
Luego para concluir captura la tecla <enter> y cuando ésta sea oprimida, modifica la última consulta quitando FIRST nn, y con esto tendrás todas las filas.

No olvides #8 es <retroceso> y #13 es <enter>.  ;)

A mí me fascinaban las búsquedas incrementales, pero éstas son algo caras actualmente. Creo que FM las desprecia.
Saludos

  • 0




IP.Board spam blocked by CleanTalk.