Grandes cantidades de datos

14/04/2007 - 03:24 por SoftMedia | Informe spam
Hola a todos,
Estoy desarrollando una aplicación en Winform y una de las cosas que hace es
cargar unos datatable desde unos archivos de texto plano mediante un parser
de texto que me he fabricado, estos archivos cada semana tienen más registros
(ya van por alrededor de 1.000.000). Estos datatables los hago que se cargen
en la base de datos (SQL Server 2005 SE) como una transacción en bloque de
con la siguiente función:

Public Function cargar_tablas(ByVal dt() As DataTable) As Boolean
Dim qs(4) As String
qs(0) = "SELECT * FROM ASUNTOS"
qs(1) = "SELECT * FROM CONTRATOS"
qs(2) = "SELECT * FROM TITULARES"
qs(3) = "SELECT * FROM MOVIMIENTOS"
qs(4) = "SELECT * FROM INTERVINIENTES"

conexion.Open()

Dim trans As SqlTransaction = conexion.BeginTransaction

Try

Dim da0 As New SqlDataAdapter()
Dim cb0 As SqlCommandBuilder = New SqlCommandBuilder(da0)
da0.SelectCommand = New SqlCommand(qs(0), conexion)
da0.SelectCommand.Transaction = trans
da0.Fill(dt(0))
da0.Update(dt(0))

Dim da1 As New SqlDataAdapter()
Dim cb1 As SqlCommandBuilder = New SqlCommandBuilder(da1)
da1.SelectCommand = New SqlCommand(qs(1), conexion)
da1.SelectCommand.Transaction = trans
da1.Fill(dt(1))
da1.Update(dt(1))

Dim da2 As New SqlDataAdapter()
Dim cb2 As SqlCommandBuilder = New SqlCommandBuilder(da2)
da2.SelectCommand = New SqlCommand(qs(2), conexion)
da2.SelectCommand.Transaction = trans
da2.Fill(dt(2))
da2.Update(dt(2))

Dim da3 As New SqlDataAdapter()
Dim cb3 As SqlCommandBuilder = New SqlCommandBuilder(da3)
da3.SelectCommand = New SqlCommand(qs(3), conexion)
da3.SelectCommand.Transaction = trans
da3.Fill(dt(3))
da3.Update(dt(3))

Dim da4 As New SqlDataAdapter()
Dim cb4 As SqlCommandBuilder = New SqlCommandBuilder(da4)
da4.SelectCommand = New SqlCommand(qs(4), conexion)
da4.SelectCommand.Transaction = trans
da4.Fill(dt(4))
da4.Update(dt(4))


trans.Commit()
Catch ex As Exception
trans.Rollback()
conexion.Close()
Return False
End Try
conexion.Close()
Return True
End Function

Hasta aquí todo bien, trada en hacerlo, pero no importa demasiado porque
solo se hace una vez por semana, pero si supierais una mejor manera, mejor.
El problema gordo está en que cuando cargo una de las tablas con muchísimos
registros en un dataset y lo visualizo en un datagridview la operación puede
tardar más de 2 minutos y esto no se puede permitir porque eso si es una
práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera mejor
para optimizar la carga de este datagridview y en general para tratar con
estas grandes cantidades de registros?
Muchas gracias de antemano.
Un saludo.

Preguntas similare

Leer las respuestas

#1 Daniel A. Calvin - Cooperator Team
14/04/2007 - 17:23 | Informe spam
Hola SoftMedia

Dividiría el problema en dos:

1 - Pasar las tablas al SQL:
No sería mucho mas eficiente aramar un paquete DTS para eso?
Hasta podrías agendar su ejecución, el manejo de datos que hace el DTS es
mucho mas eficiente y rapido.

2 -
El problema gordo está en que cuando cargo una de las tablas con
muchísimos
registros en un dataset y lo visualizo en un datagridview la operación
puede
tardar más de 2 minutos y esto no se puede permitir porque eso si es una
práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
mejor
para optimizar la carga de este datagridview y en general para tratar con
estas grandes cantidades de registros?


Aquí te hago una pregunta, en realidad mas de unam que yo ya me he hecho
hace mucho tiempo.

a - Que valor agregado tiene mostrar al usuario una grilla con 100.000
registros o 1000000 ???
b - El usuario puede explotar esa información con facilidad?
c - Que ve o que busca el usuario alli?

Mi conclusión fue:
a - no aporta nada concreto.
b - no puede explotar la información sin ayuda de alguna herramienta
adicional.
c - aquí la respuesta fue variada, tal vez lo que me ayudo a resolver el
problema fue esa variedad.

Que hice:
Cambie la forma de ver el problema, me concentre en el punto c.
Cual era la espectativa del usuario frente a la información ofrecida?
La palabra cñave es esa, INFORMACIÓN, si le muestro 100000 regiustros, o
5000, no le estoy dando información, en el mejor de los casos estoy
mostrando datos.
En función de eso ahora lo que hago es ver que información necesita el
usuario.
Ubicar un cliente?
Registros que cumplan una condición?
Valores agrupados por distintos conceptos?
Etc, etc...

Adopte entonces la filosofía de mostar aquello que represente un valor
concreto para el usuario. Ofreciendo los mecanismos para llegar al nivel de
detalle necesario.
Pero con la premisa de brindar información, no datos.

Espero que te sirvan las ideas, si necesitas que aclare algo sobre el
particular o que lo haga con ejemplos lo vemos.

Saludos

Daniel A. Calvin
Cooperator Team Member
http://www.cooperator.com.ar
Microsoft Certified Professional






"SoftMedia" escribió en el mensaje
news:
Hola a todos,
Estoy desarrollando una aplicación en Winform y una de las cosas que hace
es
cargar unos datatable desde unos archivos de texto plano mediante un
parser
de texto que me he fabricado, estos archivos cada semana tienen más
registros
(ya van por alrededor de 1.000.000). Estos datatables los hago que se
cargen
en la base de datos (SQL Server 2005 SE) como una transacción en bloque de
con la siguiente función:

Public Function cargar_tablas(ByVal dt() As DataTable) As Boolean
Dim qs(4) As String
qs(0) = "SELECT * FROM ASUNTOS"
qs(1) = "SELECT * FROM CONTRATOS"
qs(2) = "SELECT * FROM TITULARES"
qs(3) = "SELECT * FROM MOVIMIENTOS"
qs(4) = "SELECT * FROM INTERVINIENTES"

conexion.Open()

Dim trans As SqlTransaction = conexion.BeginTransaction

Try

Dim da0 As New SqlDataAdapter()
Dim cb0 As SqlCommandBuilder = New SqlCommandBuilder(da0)
da0.SelectCommand = New SqlCommand(qs(0), conexion)
da0.SelectCommand.Transaction = trans
da0.Fill(dt(0))
da0.Update(dt(0))

Dim da1 As New SqlDataAdapter()
Dim cb1 As SqlCommandBuilder = New SqlCommandBuilder(da1)
da1.SelectCommand = New SqlCommand(qs(1), conexion)
da1.SelectCommand.Transaction = trans
da1.Fill(dt(1))
da1.Update(dt(1))

Dim da2 As New SqlDataAdapter()
Dim cb2 As SqlCommandBuilder = New SqlCommandBuilder(da2)
da2.SelectCommand = New SqlCommand(qs(2), conexion)
da2.SelectCommand.Transaction = trans
da2.Fill(dt(2))
da2.Update(dt(2))

Dim da3 As New SqlDataAdapter()
Dim cb3 As SqlCommandBuilder = New SqlCommandBuilder(da3)
da3.SelectCommand = New SqlCommand(qs(3), conexion)
da3.SelectCommand.Transaction = trans
da3.Fill(dt(3))
da3.Update(dt(3))

Dim da4 As New SqlDataAdapter()
Dim cb4 As SqlCommandBuilder = New SqlCommandBuilder(da4)
da4.SelectCommand = New SqlCommand(qs(4), conexion)
da4.SelectCommand.Transaction = trans
da4.Fill(dt(4))
da4.Update(dt(4))


trans.Commit()
Catch ex As Exception
trans.Rollback()
conexion.Close()
Return False
End Try
conexion.Close()
Return True
End Function

Hasta aquí todo bien, trada en hacerlo, pero no importa demasiado porque
solo se hace una vez por semana, pero si supierais una mejor manera,
mejor.
El problema gordo está en que cuando cargo una de las tablas con
muchísimos
registros en un dataset y lo visualizo en un datagridview la operación
puede
tardar más de 2 minutos y esto no se puede permitir porque eso si es una
práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
mejor
para optimizar la carga de este datagridview y en general para tratar con
estas grandes cantidades de registros?
Muchas gracias de antemano.
Un saludo.
Respuesta Responder a este mensaje
#2 Alberto Poblacion
14/04/2007 - 17:46 | Informe spam
"SoftMedia" wrote in message
news:
Hola a todos,
Estoy desarrollando una aplicación en Winform y una de las cosas que hace
es
cargar unos datatable desde unos archivos de texto plano mediante un
parser
de texto que me he fabricado, estos archivos cada semana tienen más
registros
(ya van por alrededor de 1.000.000). Estos datatables los hago que se
cargen
en la base de datos (SQL Server 2005 SE) como una transacción en bloque de
con la siguiente función:

[...]

Hasta aquí todo bien, trada en hacerlo, pero no importa demasiado porque
solo se hace una vez por semana, pero si supierais una mejor manera,
mejor.
El problema gordo está en que cuando cargo una de las tablas con
muchísimos
registros en un dataset y lo visualizo en un datagridview la operación
puede
tardar más de 2 minutos y esto no se puede permitir porque eso si es una
práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
mejor
para optimizar la carga de este datagridview y en general para tratar con
estas grandes cantidades de registros?



No he comprendido muy bien el objetivo de la aplicación. Si el objetivo
principal es importar los archivos de texto hacia la BD en Sql Server, lo
mejor sería dejar que éste lo hiciera directamente mediante una sentencia
BULK INSERT debidamente parametrizada con la estructura de los archivos de
texto. De esta manera, los datos no necesitan ser cargados en la memoria de
la aplicación cliente.
Si tu "parser" es tan complicado que no se puede amoldar el bulk insert
para que "comprenda" el fichero de texto, entonces lo que conviene es un
único bucle que vaya leyendo linea a linea el fichero de texto, "parseando"
la linea, y grabándola en base de datos, de forma que no tengas que contener
todas las líneas en la memoria del programa cliente.

Si el objetivo principal es el de presentarlos en un datagrid para
permitir que el usuario los examine y modifique, entonces lo que conviene es
usar el datagrid en "modo virtual", usando los eventos CellValueNeeded y
CellValuePushed para traer o modificar solamente los datos que se estén
mostrando en pantalla en un momento dado, en lugar de todo el millón de
registros.
Respuesta Responder a este mensaje
#3 SoftMedia
14/04/2007 - 18:34 | Informe spam
Hola Alberto, muchas gracias por tu ayuda.
Si es cierto, debería haber utilizado un BULK INSERT. Utilizaré también lo
del modo virtual del datagrid (la verdad es que soy un poco novato en estas
lides) ya te contaré.
Ahora me encuentro con otro problema: cuando elijo un registro del datagrid
me sale una ficha, esta ficha la tengo que imprimir, para eso utilizo un
crystalreportsviewer, pero me tarda una barbaridad en mostrar la información
en el reporte. ¿Sabes si hay algo para hacer esto más rápido?

Muchas gracias por todo y perdona por mi "ignorancia".

Un saludo.

"Alberto Poblacion" wrote:

"SoftMedia" wrote in message
news:
> Hola a todos,
> Estoy desarrollando una aplicación en Winform y una de las cosas que hace
> es
> cargar unos datatable desde unos archivos de texto plano mediante un
> parser
> de texto que me he fabricado, estos archivos cada semana tienen más
> registros
> (ya van por alrededor de 1.000.000). Estos datatables los hago que se
> cargen
> en la base de datos (SQL Server 2005 SE) como una transacción en bloque de
> con la siguiente función:
>
> [...]
>
> Hasta aquí todo bien, trada en hacerlo, pero no importa demasiado porque
> solo se hace una vez por semana, pero si supierais una mejor manera,
> mejor.
> El problema gordo está en que cuando cargo una de las tablas con
> muchísimos
> registros en un dataset y lo visualizo en un datagridview la operación
> puede
> tardar más de 2 minutos y esto no se puede permitir porque eso si es una
> práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
> registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
> mejor
> para optimizar la carga de este datagridview y en general para tratar con
> estas grandes cantidades de registros?

No he comprendido muy bien el objetivo de la aplicación. Si el objetivo
principal es importar los archivos de texto hacia la BD en Sql Server, lo
mejor sería dejar que éste lo hiciera directamente mediante una sentencia
BULK INSERT debidamente parametrizada con la estructura de los archivos de
texto. De esta manera, los datos no necesitan ser cargados en la memoria de
la aplicación cliente.
Si tu "parser" es tan complicado que no se puede amoldar el bulk insert
para que "comprenda" el fichero de texto, entonces lo que conviene es un
único bucle que vaya leyendo linea a linea el fichero de texto, "parseando"
la linea, y grabándola en base de datos, de forma que no tengas que contener
todas las líneas en la memoria del programa cliente.

Si el objetivo principal es el de presentarlos en un datagrid para
permitir que el usuario los examine y modifique, entonces lo que conviene es
usar el datagrid en "modo virtual", usando los eventos CellValueNeeded y
CellValuePushed para traer o modificar solamente los datos que se estén
mostrando en pantalla en un momento dado, en lugar de todo el millón de
registros.



Respuesta Responder a este mensaje
#4 Alberto Poblacion
14/04/2007 - 19:21 | Informe spam
"SoftMedia" wrote in message
news:
[...] utilizo un
crystalreportsviewer, pero me tarda una barbaridad en mostrar la
información
en el reporte. ¿Sabes si hay algo para hacer esto más rápido?



La verdad es que le tengo un poco de manía al Crystal Reports, por la
cantidad de problemas que da para conseguir que funcione como quieres y para
distribuir las aplicaciones y conseguir que se instale correctamente, Asi
que procuro evitar usarlo siempre que puedo. Por ejemplo, para listados
sencillos a veces prefiero usar un PrintDocument y dibujar la página con
GDI+.

Pero en fín, si no tienes más remedio que usarlo comprueba una cosa:
cerciórate de que la ficha que estás imprimiendo la sacas con un
SELECT...WHERE... y en el where especificas el registro que quieres. No
configures el Cystal para que envíe el SELECT sin condiciones, indicándole
luego en los filtros la ficha que quieres, porque entonces se trae desde la
base de datos el millón de registros y luego los examina uno a uno buscando
el que quieres imprimir. Obviamente, esto es lento.
Si la sentencia la tienes bien puesta con el WHERE, pruébala a mano en
Sql Server a ver cuánto tarda. Si es lenta, la causa probable es que no
tienes indexado el campo o campos especificados en el Where. Y si están
indexados y sigue siendo lento, entonces te falta ejecutar un "update
statistics".
Respuesta Responder a este mensaje
#5 SoftMedia
15/04/2007 - 01:44 | Informe spam
Hola Daniel,
Muchas gracias por tus ideas, me han servido para recapacitar y he optado
por rediseñar el asunto de la grilla (como tu la llamas).
Con respecto al DTS decirte que soy un poco novato con estos temas y no se
exáctamente como se hace. ¿Serías tan amable de indicarme los pasos a seguir
o alguna url donde venga bien explicado? Si ya tengo los datos de las cinco
tabla sacadas de los archivos de texto en sendos datatables, ¿como hago para
subirlas al servidor de sql server?

Muchas gracias de nuevo. Eres muy amable.
Recibe un cordial saludo.

"Daniel A. Calvin - Cooperator Team" wrote:

Hola SoftMedia

Dividiría el problema en dos:

1 - Pasar las tablas al SQL:
No sería mucho mas eficiente aramar un paquete DTS para eso?
Hasta podrías agendar su ejecución, el manejo de datos que hace el DTS es
mucho mas eficiente y rapido.

2 -
> El problema gordo está en que cuando cargo una de las tablas con
> muchísimos
> registros en un dataset y lo visualizo en un datagridview la operación
> puede
> tardar más de 2 minutos y esto no se puede permitir porque eso si es una
> práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
> registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
> mejor
> para optimizar la carga de este datagridview y en general para tratar con
> estas grandes cantidades de registros?
Aquí te hago una pregunta, en realidad mas de unam que yo ya me he hecho
hace mucho tiempo.

a - Que valor agregado tiene mostrar al usuario una grilla con 100.000
registros o 1000000 ???
b - El usuario puede explotar esa información con facilidad?
c - Que ve o que busca el usuario alli?

Mi conclusión fue:
a - no aporta nada concreto.
b - no puede explotar la información sin ayuda de alguna herramienta
adicional.
c - aquí la respuesta fue variada, tal vez lo que me ayudo a resolver el
problema fue esa variedad.

Que hice:
Cambie la forma de ver el problema, me concentre en el punto c.
Cual era la espectativa del usuario frente a la información ofrecida?
La palabra cñave es esa, INFORMACIÓN, si le muestro 100000 regiustros, o
5000, no le estoy dando información, en el mejor de los casos estoy
mostrando datos.
En función de eso ahora lo que hago es ver que información necesita el
usuario.
Ubicar un cliente?
Registros que cumplan una condición?
Valores agrupados por distintos conceptos?
Etc, etc...

Adopte entonces la filosofía de mostar aquello que represente un valor
concreto para el usuario. Ofreciendo los mecanismos para llegar al nivel de
detalle necesario.
Pero con la premisa de brindar información, no datos.

Espero que te sirvan las ideas, si necesitas que aclare algo sobre el
particular o que lo haga con ejemplos lo vemos.

Saludos

Daniel A. Calvin
Cooperator Team Member
http://www.cooperator.com.ar
Microsoft Certified Professional






"SoftMedia" escribió en el mensaje
news:
> Hola a todos,
> Estoy desarrollando una aplicación en Winform y una de las cosas que hace
> es
> cargar unos datatable desde unos archivos de texto plano mediante un
> parser
> de texto que me he fabricado, estos archivos cada semana tienen más
> registros
> (ya van por alrededor de 1.000.000). Estos datatables los hago que se
> cargen
> en la base de datos (SQL Server 2005 SE) como una transacción en bloque de
> con la siguiente función:
>
> Public Function cargar_tablas(ByVal dt() As DataTable) As Boolean
> Dim qs(4) As String
> qs(0) = "SELECT * FROM ASUNTOS"
> qs(1) = "SELECT * FROM CONTRATOS"
> qs(2) = "SELECT * FROM TITULARES"
> qs(3) = "SELECT * FROM MOVIMIENTOS"
> qs(4) = "SELECT * FROM INTERVINIENTES"
>
> conexion.Open()
>
> Dim trans As SqlTransaction = conexion.BeginTransaction
>
> Try
>
> Dim da0 As New SqlDataAdapter()
> Dim cb0 As SqlCommandBuilder = New SqlCommandBuilder(da0)
> da0.SelectCommand = New SqlCommand(qs(0), conexion)
> da0.SelectCommand.Transaction = trans
> da0.Fill(dt(0))
> da0.Update(dt(0))
>
> Dim da1 As New SqlDataAdapter()
> Dim cb1 As SqlCommandBuilder = New SqlCommandBuilder(da1)
> da1.SelectCommand = New SqlCommand(qs(1), conexion)
> da1.SelectCommand.Transaction = trans
> da1.Fill(dt(1))
> da1.Update(dt(1))
>
> Dim da2 As New SqlDataAdapter()
> Dim cb2 As SqlCommandBuilder = New SqlCommandBuilder(da2)
> da2.SelectCommand = New SqlCommand(qs(2), conexion)
> da2.SelectCommand.Transaction = trans
> da2.Fill(dt(2))
> da2.Update(dt(2))
>
> Dim da3 As New SqlDataAdapter()
> Dim cb3 As SqlCommandBuilder = New SqlCommandBuilder(da3)
> da3.SelectCommand = New SqlCommand(qs(3), conexion)
> da3.SelectCommand.Transaction = trans
> da3.Fill(dt(3))
> da3.Update(dt(3))
>
> Dim da4 As New SqlDataAdapter()
> Dim cb4 As SqlCommandBuilder = New SqlCommandBuilder(da4)
> da4.SelectCommand = New SqlCommand(qs(4), conexion)
> da4.SelectCommand.Transaction = trans
> da4.Fill(dt(4))
> da4.Update(dt(4))
>
>
> trans.Commit()
> Catch ex As Exception
> trans.Rollback()
> conexion.Close()
> Return False
> End Try
> conexion.Close()
> Return True
> End Function
>
> Hasta aquí todo bien, trada en hacerlo, pero no importa demasiado porque
> solo se hace una vez por semana, pero si supierais una mejor manera,
> mejor.
> El problema gordo está en que cuando cargo una de las tablas con
> muchísimos
> registros en un dataset y lo visualizo en un datagridview la operación
> puede
> tardar más de 2 minutos y esto no se puede permitir porque eso si es una
> práctica habitual y crítica. Yo solo he trabajado con datasets y pocos
> registros y esto se me hace un poco cuesta arriba, ¿Hay alguna manera
> mejor
> para optimizar la carga de este datagridview y en general para tratar con
> estas grandes cantidades de registros?
> Muchas gracias de antemano.
> Un saludo.



Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida