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

#11 SoftMedia
15/04/2007 - 22:28 | Informe spam
Muchas gracias, voy a intentar lo del printdocument y ya te iré contando.
Con respecto a lo de los datatables, ¿crees que debo seguir con lo del BULK
INSERT o me creo una función para que vaya metiendo en la base de datos los
registros a medida que se van sacando del archivo de texto?
Reitero mi agracecimiento.
Un cordial saludo.

"Alberto Poblacion" wrote:

"SoftMedia" wrote in message
news:
> ¿Hasta cuantos registros aguantan los datatables? Ten en cuenta que
> estamos
> hablando de millones de registros y creciendo...

El límite de registros del datatable viene impuesto por el hecho de que
todos ellos se cargan en memoria simultaneamente. Por ejemplo, si tienes 1
Gigabyte de memoria virtual disponible para tu programa, y cada registro
mide 2000 bytes (en el formato interno en que los guarde el datatable, por
ejemplo, los strings son Unicode y por tanto gastan 2 bytes por carácter),
pues entonces te cabría algo menos de medio millón de registros.

Desde luego, si estamos hablando de millones de registros, no es nada
recomendable almacenarlos en un datatable. Conviene modificar el proceso
para que los vaya salvando a la vez que los lee, para no tener que cargarlos
todos a la vez en memoria.


> Con respecto a lo que me dices en los anteriores posts del asunto de
> crystalreports me ha llamado la atención lo de los printdocuments y gdi+,
> es
> posible que sea la solución a mis "penas" ya que los reports no son
> excesivamente complejos. ¿Serías tan amable de explicarme un poco mejor
> como
> se haría esto? No obstante voy a intentar optimizar las consultas tal como
> me
> dices.

El PrintDocument es un Control que tiene un método llamado Print. Cuando
lo llamas, dispara un evento llamado PrintPage, al cual le llega dentro del
EventArgs un objeto de tipo Graphics. Con ese Graphics, se van ejecutando
los métodos de dibujo de GDI+, de forma que vas haciendo DrawLine,
DrawString, etc, para dibujar la página tal como quieras que salga impresa.
Si hay más páginas, devuelves e.HasMorePages=True, y se vuelve a disparar el
evento para que dibujes la siguiente página. El PrintDocument tiene varias
propiedades para seleccionar la impresora, la configuración de la página,
etc., y también tiene la previsualización en pantalla del documento antes de
mandarlo a impresora.



Respuesta Responder a este mensaje
#12 Alberto Poblacion
15/04/2007 - 22:58 | Informe spam
"SoftMedia" wrote in message
news:
Muchas gracias, voy a intentar lo del printdocument y ya te iré contando.
Con respecto a lo de los datatables, ¿crees que debo seguir con lo del
BULK
INSERT o me creo una función para que vaya metiendo en la base de datos
los
registros a medida que se van sacando del archivo de texto?



Depende de cómo de sencillo sea el fichero. Por ejemplo, si son simples
campos encerrados entre comillas y separados por comas, es muy sencillo
leerlo con el bulk insert, y en una sola sentencia resuelves todo el
traspaso de datos. Por el contrario, si es un fichero muy complejo de
analizar, y se necesita pasar por el "parser" que ya tienes hecho, entonces
lo mejor es modificar la rutina que ya tienes hecha para que vaya grabando
los datos según los obtiene, en lugar de cargarlos todos en memoria y
grabarlos en una segunda fase.
Respuesta Responder a este mensaje
#13 SoftMedia
16/04/2007 - 20:46 | Informe spam
Hola de nuevo,
Los archivos de texto no son especialmente complejos, pero eso sí, los
campos son de ancho fijo, no están separados por ningún caracter. ¿Es posible
hacer esto con el bulk insert?
Muchísimas gracias de nuevo.
Un saludo.

"Alberto Poblacion" wrote:

"SoftMedia" wrote in message
news:
> Muchas gracias, voy a intentar lo del printdocument y ya te iré contando.
> Con respecto a lo de los datatables, ¿crees que debo seguir con lo del
> BULK
> INSERT o me creo una función para que vaya metiendo en la base de datos
> los
> registros a medida que se van sacando del archivo de texto?

Depende de cómo de sencillo sea el fichero. Por ejemplo, si son simples
campos encerrados entre comillas y separados por comas, es muy sencillo
leerlo con el bulk insert, y en una sola sentencia resuelves todo el
traspaso de datos. Por el contrario, si es un fichero muy complejo de
analizar, y se necesita pasar por el "parser" que ya tienes hecho, entonces
lo mejor es modificar la rutina que ya tienes hecha para que vaya grabando
los datos según los obtiene, en lugar de cargarlos todos en memoria y
grabarlos en una segunda fase.


Respuesta Responder a este mensaje
#14 Alberto Poblacion
16/04/2007 - 21:20 | Informe spam
"SoftMedia" wrote in message
news:
Los archivos de texto no son especialmente complejos, pero eso sí, los
campos son de ancho fijo, no están separados por ningún caracter. ¿Es
posible
hacer esto con el bulk insert?



Sí: Se hace "BULK INSERT LaTabla FROM 'c:\datos.txt' WITH
(FORMATFILE='C:\formato.xml')"

Y en el archivo formato.xml se describen las longitudes y tipos de los
campos. La estructura del archivo de formato es parecida a lo siguiente:

<?xml version="1.0"?>
<BCPFORMAT
xmlns="http://schemas.microsoft.com/sqlser...rmat"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-in...">
<RECORD>
<FIELD ID="1" xsi:type="CharFixed" LENGTH="10"/>
<FIELD ID="2" xsi:type="CharFixed" LENGTH="6"/>
<FIELD ID="3" xsi:type="CharTerm" TERMINATOR=""
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="Campo1" xsi:type="SQLINT" />
<COLUMN SOURCE="2" NAME="Campo2" xsi:type="SQLINT" />
</ROW>
</BCPFORMAT>
Respuesta Responder a este mensaje
#15 SoftMedia
16/04/2007 - 23:12 | Informe spam
Muchas gracias Alberto.
Te recuerdo que soy un poco novato en esto así que te voy a hacer una
pregunta puede que te resulte tonta: ¿Donde pongo la sentencia bulk insert y
dónde he de ubicar los archivos txt y xml?
Muchísimas gracias. Me estás siendo de gran ayuda.
Un cordial saludo.

"Alberto Poblacion" wrote:

"SoftMedia" wrote in message
news:
> Los archivos de texto no son especialmente complejos, pero eso sí, los
> campos son de ancho fijo, no están separados por ningún caracter. ¿Es
> posible
> hacer esto con el bulk insert?

Sí: Se hace "BULK INSERT LaTabla FROM 'c:\datos.txt' WITH
(FORMATFILE='C:\formato.xml')"

Y en el archivo formato.xml se describen las longitudes y tipos de los
campos. La estructura del archivo de formato es parecida a lo siguiente:

<?xml version="1.0"?>
<BCPFORMAT
xmlns="http://schemas.microsoft.com/sqlser...rmat"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-in...">
<RECORD>
<FIELD ID="1" xsi:type="CharFixed" LENGTH="10"/>
<FIELD ID="2" xsi:type="CharFixed" LENGTH="6"/>
<FIELD ID="3" xsi:type="CharTerm" TERMINATOR=""
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="Campo1" xsi:type="SQLINT" />
<COLUMN SOURCE="2" NAME="Campo2" xsi:type="SQLINT" />
</ROW>
</BCPFORMAT>


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