Por lo tanto, estoy trabajando en una base de datos que agregaré a mis futuros proyectos como una especie de db de soporte, pero estoy teniendo un poco de problema con eso, especialmente los registros.Sql Server 2008 Sintonización de grandes transacciones (700k + filas/transacción)
La base de datos, básicamente, debe actualizarse una vez al mes. La tabla principal debe purgarse y luego rellenarse de un archivo CSV. El problema es que el Servidor SQL generará un registro para él que es MEGA grande. Logré llenarlo una vez, pero quería probar todo el proceso purgándolo y volviéndolo a llenar.
Ahí es cuando me aparece un error que indica que el archivo de registro está lleno. Salta de 88MB (después de la reducción a través del plan de mantenimiento) a 248MB y luego detiene el proceso por completo y nunca se completa.
He limitado su crecimiento a 256MB, incrementando en 16MB, razón por la cual falló, pero en realidad no necesito registrar nada en absoluto. ¿Hay alguna forma de eludir por completo el inicio de sesión en cualquier consulta que se ejecute en la base de datos?
Gracias por cualquier respuesta con anticipación!
EDIT: Por las sugerencias de @ mattmc3 Implementé SqlBulkCopy para todo el procedimiento. Funciona INCREÍBLE, excepto que mi bucle de alguna manera se cuelga en el último trozo restante que necesita insertarse. No estoy muy seguro de dónde me estoy equivocando, diablos, ni siquiera sé si este es un ciclo correcto, por lo que agradecería algo de ayuda.
Sé que es un problema con las últimas llamadas GetDataTable o SetSqlBulkCopy. Estoy tratando de insertar filas 788189, 788000 entrar y los 189 restantes están cayendo ...
string[] Rows;
using (StreamReader Reader = new StreamReader("C:/?.csv")) {
Rows = Reader.ReadToEnd().TrimEnd().Split(new char[1] {
'\n'
}, StringSplitOptions.RemoveEmptyEntries);
};
int RowsInserted = 0;
using (SqlConnection Connection = new SqlConnection("")) {
Connection.Open();
DataTable Table = null;
while ((RowsInserted < Rows.Length) && ((Rows.Length - RowsInserted) >= 1000)) {
Table = GetDataTable(Rows.Skip(RowsInserted).Take(1000).ToArray());
SetSqlBulkCopy(Table, Connection);
RowsInserted += 1000;
};
Table = GetDataTable(Rows.Skip(RowsInserted).ToArray());
SetSqlBulkCopy(Table, Connection);
Connection.Close();
};
static DataTable GetDataTable(
string[] Rows) {
using (DataTable Table = new DataTable()) {
Table.Columns.Add(new DataColumn("A"));
Table.Columns.Add(new DataColumn("B"));
Table.Columns.Add(new DataColumn("C"));
Table.Columns.Add(new DataColumn("D"));
for (short a = 0, b = (short)Rows.Length; a < b; a++) {
string[] Columns = Rows[a].Split(new char[1] {
','
}, StringSplitOptions.RemoveEmptyEntries);
DataRow Row = Table.NewRow();
Row["A"] = Columns[0];
Row["B"] = Columns[1];
Row["C"] = Columns[2];
Row["D"] = Columns[3];
Table.Rows.Add(Row);
};
return (Table);
};
}
static void SetSqlBulkCopy(
DataTable Table,
SqlConnection Connection) {
using (SqlBulkCopy SqlBulkCopy = new SqlBulkCopy(Connection)) {
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("A", "A"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("B", "B"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("C", "C"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("D", "D"));
SqlBulkCopy.BatchSize = Table.Rows.Count;
SqlBulkCopy.DestinationTableName = "E";
SqlBulkCopy.WriteToServer(Table);
};
}
EDITAR/código final: lo que la aplicación ya está terminado y maravillosas obras, y bastante rápido! @ mattmc3, gracias por toda la ayuda! Aquí está el código final para cualquier persona que les puede resultar útil:
List<string> Rows = new List<string>();
using (StreamReader Reader = new StreamReader(@"?.csv")) {
string Line = string.Empty;
while (!String.IsNullOrWhiteSpace(Line = Reader.ReadLine())) {
Rows.Add(Line);
};
};
if (Rows.Count > 0) {
int RowsInserted = 0;
DataTable Table = new DataTable();
Table.Columns.Add(new DataColumn("Id"));
Table.Columns.Add(new DataColumn("A"));
while ((RowsInserted < Rows.Count) && ((Rows.Count - RowsInserted) >= 1000)) {
Table = GetDataTable(Rows.Skip(RowsInserted).Take(1000).ToList(), Table);
PerformSqlBulkCopy(Table);
RowsInserted += 1000;
Table.Clear();
};
Table = GetDataTable(Rows.Skip(RowsInserted).ToList(), Table);
PerformSqlBulkCopy(Table);
};
static DataTable GetDataTable(
List<string> Rows,
DataTable Table) {
for (short a = 0, b = (short)Rows.Count; a < b; a++) {
string[] Columns = Rows[a].Split(new char[1] {
','
}, StringSplitOptions.RemoveEmptyEntries);
DataRow Row = Table.NewRow();
Row["A"] = "";
Table.Rows.Add(Row);
};
return (Table);
}
static void PerformSqlBulkCopy(
DataTable Table) {
using (SqlBulkCopy SqlBulkCopy = new SqlBulkCopy(@"", SqlBulkCopyOptions.TableLock)) {
SqlBulkCopy.BatchSize = Table.Rows.Count;
SqlBulkCopy.DestinationTableName = "";
SqlBulkCopy.WriteToServer(Table);
};
}
Algunas sugerencias si quiere acelerar esto aún más. 1.) En lugar de hacer Reader.ReadToEnd(), haz un ciclo y haz Reader.ReadLine() una línea a la vez. Tomará menos memoria. 2.) Si nadie accederá a su mesa durante el tiempo que la está cargando, use la opción 'SqlBulkCopyOptions.TableLock'. 3.) Solo para guardar un código, el objeto SqlBulkCopy infiere las asignaciones de columna si asigna el mismo nombre a las columnas que las que están en su tabla de destino, y como está gestionando la fragmentación usted mismo, no hay ninguna razón para configurar el .BatchSize tampoco. Feliz codificación! – mattmc3
Sobre el tema de inferir las columnas, ¿funcionará si: 'DBTable = {Id (PK, IDENTIDAD), A, B, C, D}', pero 'DataTable = {A, B, C, D}'? Creo que me estaba dando problemas, por eso los especifiqué, pero, de nuevo, podría haberlo estado jodiendo de alguna manera ... – Gup3rSuR4c
¡Bien, ya está! ¡Implementé todo lo que me recomendó y funciona INCREÍBLE! La memoria se redujo a la mitad a ~ 85MB y toda la operación tarda aproximadamente 45 segundos en completarse. Y descubrí las columnas de arriba, tenía razón, pero acabo de agregar un marcador de posición para el 'Id' y funcionó. '¡GRACIAS POR AYUDARME EN ESTO Y POR ENSEÑARME SOBRE COSAS QUE NUNCA SABÍA!' – Gup3rSuR4c