Autor Tema: DataAdapter.fill(dataset,'nombre de la tabla') [DEMASIADO LENTO AL POBLARSE]  (Leído 18395 veces)

0 Usuarios y 1 Visitante están viendo este tema.

sicario

  • Visitante
Señores... pido las disculpas del caso, pero me veo en la necesidad de buscar ayuda entre ustedes, pues espero mas de alguno ya ha tenido este dolorcito de cabeza.

Tengo una aplicacion que en terminos generales todo va bien... resulta que mi aplicacioncilla, pretende ser una herramienta versatil para un DBA. Pero me pone en aprietos que cuando hago un select * a determinadas tablas, el evento dataadapter.fill se tarda demasiado en poblarme mi dataset.

La pregunta especifica es.... ¿que puedo hacer para poblar los dataset mas rapido?

'******** PEDAZO DE MI CODIGO ************************
              ConnRecordset = New Npgsql.NpgsqlConnection(constr)
              SQLQuery = SQLstr
              operation_finished = False
              dadapterPostGre = New Npgsql.NpgsqlDataAdapter (SQLQuery, ConnRecordset)
              dadapterPostGre.MissingSchemaAction = MissingSchemaAction.AddWithKey
              dadapterPostGre.MissingMappingAction = MissingMappingAction.Passthrough
              dset = New DataSet
              dtable = New DataTable
              dtable = dset.Tables.Add('Table')
              dadapterPostGre.Fill(dset, 'Table')

'**************************************

Desconectado Jonhyrey

  • Sv Full Member
  • *
  • Mensajes: 559
Proba así:

        Dim Tabla As New DataTable
        Dim reader As New SqlClient.SqlCommand("Select * From Clientes", sqlConn)
        Dim read As SqlClient.SqlDataReader = reader.ExecuteReader

        Tabla.Load(reader)

Puedes buscar más información acerca del metodo Load un DataTable.

Espero te ayude



Desconectado Jonhyrey

  • Sv Full Member
  • *
  • Mensajes: 559
Has probado la solucion que te di??, es más eficiente llenar el datatable así o resulta lo mismo??



sicario

  • Visitante
Has probado la solucion que te di??, es más eficiente llenar el datatable así o resulta lo mismo??

ey gracias... pero lo que necesito es utilizar un Dataset... no un datareader ... porque no me permitiria el datareader aplicar cambios a dichas consultas.. para almacenar en tabla posteriormente

Desconectado Jonhyrey

  • Sv Full Member
  • *
  • Mensajes: 559
Es que el dataReader sustituye la funcion Fill del DataTable, solo lo utilizas para optimizar la funcion de llenado de x tabla



Desconectado Juancho

  • The Communiter-
  • *
  • Mensajes: 1311
Es que el dataReader sustituye la funcion Fill del DataTable, solo lo utilizas para optimizar la funcion de llenado de x tabla

no. xq si t has dado cuenta el data reader lo que va haciendo es rellenar un data set y el data reader vs vas registro por registro. Aunq eso si si ocupas un datareader si es muchisimo mas rapido aunq si dijeras un poquito como que es lo que qurees hacer realment te prodia ayudar un poqutio mas. Porque a mi una vez m pasaba eso con un programa d facturacion que el importe de un BD de access eran mas d 30 mil registro entonces casi en rellenar el data set c me tardaba como alrededor 40s a 50s pero cuando lo hic x medio d un datareader casi se me tardo 10s gran diferencia y lo que podes hacer como en el datareader vas leyendo registro por registro podes:
-primero crear una nueva tabla y todo lo demas
y d ahi por medio de un FOR EACH vas rellenando tu tabla nuevo recorriendo registro por registro del datareader y asi lo vas llenando. Asi m acuerdo que creo q yo lo hacia y casi m ahorre como 30s d carga y muchisimo mas rapido. Aunq yo lo hic asi xq hacia formulas al agregar el nuevo registro a la tabal que queria mostrar vs. Y ya asi solo actualizas los datos y ya lo pasas a la base de datos.

O sino la otroa forma que podes hacer ees programar en multihilo. Asi si tenes problemas que vez que la apliacion c t traba mientras esta cargando los datos. La operacion de carga o de ir a rellenar la tabla hacela en multihilo para la aplicacion maestra no c quedes asi trabada!

Cualquier duda m preguntas!!  :thumbsup:
<a href="http://www.gametracker.com/player/%7BAiPI%7DJuancho/94.127.17.72:11480/" target="_blank">
<img src="http://cache.www.gametracker.com/player/%7BAiPI%7DJuancho/94.127.17.72:11480/b_560x95.png" border="0" width="560" height="95" alt="" />
</a>

sicario

  • Visitante
va el pique esta asi:

Se me ha pedido que "re-invente la rueda". Hacer un programa que permita correr SCRIPT de diferente indole en DB's. El problema redunda cuando existen algunas tablas que su cantidad de registros supera los 500 mil. y haces un "select * from " entonces... es que el Dataset se me agueva. al momento de poblarse...

basicamente lo que necesito hacer es que el programita siendo un editor de sentencias SQL me  pueda devolver en dos patadas los resultados de cualesquiera de las consultas que alli se ejecuten... algo asi como un "SQL QUERY".  Los resultados seran devueltos en un datagrid para luego dar la posibilidad de exportarlos a cualquier otro formato.

OJO:  Mi problema nada mas es al momento de poblar el Dataset.

¿si me explique?

Desconectado mxgxw

  • Global Moderator
  • The Communiter-
  • *
  • Mensajes: 5666
  • Starlet - 999cc
    • mxgxw
va el pique esta asi:

Se me ha pedido que "re-invente la rueda". Hacer un programa que permita correr SCRIPT de diferente indole en DB's. El problema redunda cuando existen algunas tablas que su cantidad de registros supera los 500 mil. y haces un "select * from " entonces... es que el Dataset se me agueva. al momento de poblarse...

basicamente lo que necesito hacer es que el programita siendo un editor de sentencias SQL me  pueda devolver en dos patadas los resultados de cualesquiera de las consultas que alli se ejecuten... algo asi como un "SQL QUERY".  Los resultados seran devueltos en un datagrid para luego dar la posibilidad de exportarlos a cualquier otro formato.

OJO:  Mi problema nada mas es al momento de poblar el Dataset.

¿si me explique?

mira se me ocurre... no obtengas todos los registros, usa LIMIT y los vas obteniendo por bloques de 100 por ejemplo. El problema es que en tu aplicación vas a tener que programar de alguna manera que detecte cuando ya se quiere pasar a los siguientes 100... Cuando tengas demasiados datos no los obtengas todos de una vez, a menos que tengas planeado guardarlos en un archivo o algo. Si lo haces entonces tu programa va a gastar más memoria y se va a poner lento.

Si tu programa va a "operar" los resultados (que creo que no es el caso porque solo has dicho que tarda en llenar); igual, podes ir obteniendo los resultados en bloques e ir operandolos de esa manera, la idea es que no llenes un dataset en memoria con todos los registros de la DB, eso lo tiene que hacer la DB no el programa cliente. Si son muchos los registros cortalos en piezas mas pequeñas y procesalos en bloques.

Cuando tengamos una maquina de touring completa pues talvez podas cargar todos esos datos en memoria sin penalización de rendimiento jejejeje
« Última Modificación: enero 10, 2008, 08:54:34 am por mxgxw »


sicario

  • Visitante
el caso es MX ... que tengo un programita en C++ ... visual C++ .. y esa consulta de la que hablo la hace en... 18 milesimas de segundos... uta... donde queda .NET? ese es mi rollo.. y la lentitud esta en poblar el DATA SET ... un no he medido cuanto se tardaria al llenar la GRIDVIEW O LISVIEW.


sicario

  • Visitante
AUXILIO:

el DATAREADER efectivamente es mas rapido... peroe el clavo ahora es vaciar eso a un datalistview ...... no puedo hacerle binding  :-/

Desconectado rdoggsv

  • Administrator
  • The Communiter-
  • *
  • Mensajes: 6531
  • "Once you go arch , u never go back"
    • SV CommunitY
El datareader es exactamente solo para eso man para leer, si le vas hacer algun cambio a la información podrías enviarlo manualemente y no con asosciaciones.

Pro eso es bien rápido porque es para lectura e inclusive en un solo sentido, "de una via"

sicario

  • Visitante
lo se rdog... mi problema es que ahora se ejecuta rapido la consulta... pero lo que necesito es mostrarlos de manera rapida tambien en un lisview o algo

Desconectado rdoggsv

  • Administrator
  • The Communiter-
  • *
  • Mensajes: 6531
  • "Once you go arch , u never go back"
    • SV CommunitY
Hace el tipico while en el metodo read para ir pasando por todos los registros :)

Desconectado vlad

  • Global Moderator
  • The Communiter-
  • *
  • Mensajes: 6351
    • Qualium.net
Una ves nada mas tuve que llenar listas con miles de elementos (unas coordenadas) y ahora que me pongo a pensar en el problema de ¤.§íĈÅRïð.¤, debe de ser el mismo que tuve en ese momento: cada vez que agrega un registro/elemento a la lista, tiene que actualizarse la lista y esto genera el cuello de botella.

En resumen, una solución practica fue bloquear la actualizacion de la lista hasta que se terminara de llenar/poblar.

El problema es que esto lo hago en VB6, en .NET no estoy seguro que pueda hacerse lo mismo.

Basicamente ocupas esta API:
Código: [Seleccionar]
Public Declare Function LockWindowUpdate _
               Lib "user32" (ByVal hwndLock As Long) As Long

Donde hwndLock es el hwnd del control a bloquear -y si no tiene- entonces se puede usar el hwnd de la ventana que contiene el control.

El control se bloquea justo antes de empezar a llenarlo de datos y luego se desbloquea ejecutando la API con hwndLock = 0.


Ahora bien, un rapido vistazo en Google me da indicios de que esto no funciona en VB.net, pero encontré esto: Preventing controls from redrawing

No digo que vas a reducir en un 70% o 90% el tiempo de espera, pero como bien sabras, cualquier ganancia en velocidad es siempre bien recibida  ohyea:

Desconectado arnaldobenitez

  • The newbie
  • *
  • Mensajes: 1
Señores... pido las disculpas del caso, pero me veo en la necesidad de buscar ayuda entre ustedes, pues espero mas de alguno ya ha tenido este dolorcito de cabeza.

Tengo una aplicacion que en terminos generales todo va bien... resulta que mi aplicacioncilla, pretende ser una herramienta versatil para un DBA. Pero me pone en aprietos que cuando hago un select * a determinadas tablas, el evento dataadapter.fill se tarda demasiado en poblarme mi dataset.

La pregunta especifica es.... ¿que puedo hacer para poblar los dataset mas rapido?

'******** PEDAZO DE MI CODIGO ************************
              ConnRecordset = New Npgsql.NpgsqlConnection(constr)
              SQLQuery = SQLstr
              operation_finished = False
              dadapterPostGre = New Npgsql.NpgsqlDataAdapter (SQLQuery, ConnRecordset)
              dadapterPostGre.MissingSchemaAction = MissingSchemaAction.AddWithKey
              dadapterPostGre.MissingMappingAction = MissingMappingAction.Passthrough
              dset = New DataSet
              dtable = New DataTable
              dtable = dset.Tables.Add('Table')
              dadapterPostGre.Fill(dset, 'Table')

'**************************************

Por extraño que parezca, buscando en la web encontré una solución un tanto extraña pero funcionó. La idea es declarar dentro del cuerpo del stored procedure las variables que se van a utilizar para filtrar los datos en el where y no emplear directamente los parámetros de entrada. O sea, puenteando los filtros. No se bien por qué pero funciona. Este es el ejemplo de mi procedure:

ALTER PROCEDURE [dbo].[sp_SelParaConciliacion]
@nLegajo1 int,
@nTipo1 tinyint --1 Ver Ingresos Sin Egresos  //  2 Ver Egresos Sin Ingresos
AS
BEGIN
   
   
   SET NOCOUNT ON;
--Declaro variables de los mismos tipos empleados como parámetros
DECLARE @nLegajo int
DECLARE @nTipo tinyint

--Asigno los parámetros de entrada a las variables creadas
SET @nLegajo = @nLegajo1
SET @nTipo=@nTipo1
   
 
--Utilizo las variables creadas para filtrar los datos
   SELECT nIdTabla  AS CodigoTabla,
            CASE WHEN @nTipo = 1 THEN HoraIngreso  else HoraEgreso end AS Hora,
             dbo.Fn_DiaDeLaSemana(CASE WHEN @nTipo = 1 THEN HoraIngreso  else HoraEgreso end) AS Situacion
            ,CASE WHEN (SELECT COUNT(FP.nEstado)
                        FROM SisFichadasPlano FP
                        WHERE FP.nEstado  = 1 and FP.nLegajo =@nLegajo
                        GROUP BY  FP.nLegajo) > 0 THEN '( * )' ELSE '' END AS Automatico,
                        nIdTabla, 0 AS Checkeado
   FROM         SisFichadasPlano INNER JOIN
                      PerPefiles ON SisFichadasPlano.nLegajo = PerPefiles.sCodTango
    WHERE nLegajo=@nLegajo
    AND ((@nTipo = 1 and  nIdRelojSalida= 0 and nIdRelojEntrada>0) or (@nTipo = 2 and  nIdRelojEntrada= 0 and nIdRelojSalida>0))
   AND SisFichadasPlano.nEstado = 0
   AND PerPefiles.nEstado in(4,5,6)
    ORDER BY nIdTabla
   
END