Historia¿Cómo acelerar las inserciones LINQ con SQL CE?
que tienen una lista de "registros" (3500), que guardo a XML y comprimir al salir del programa. Desde:
- el número de los registros aumenta
- sólo alrededor de 50 registros deben ser actualizados en la salida
- de guardado tiene unos 3 segundos
que necesitaba otra solución - base de datos integrada. Elegí SQL CE, ya que funciona con VS sin ningún problema y la licencia está bien para mí (he comparado a Firebird, SQLite, EffiProz, db4o y BerkeleyDB).
Los datos
La estructura de registro: 11 campos, 2 de ellas se integra en la clave principal (nvarchar + byte). Otros registros son bytes, datatimes, double y ints.
No utilizo ninguna relación, combinación, índice (excepto la clave principal), disparadores, vistas, etc. En realidad, es un diccionario plano: pares de clave + valor. Modifico algunos de ellos, y luego tengo que actualizarlos en la base de datos. De vez en cuando agrego algunos "registros" nuevos y necesito almacenarlos (insertarlos). Eso es todo.
enfoque LINQ
tengo la base de datos en blanco (archivo), así que hago 3500 insertos en un bucle (uno por uno). Ni siquiera compruebo si el registro ya existe porque db está en blanco.
¿Tiempo de ejecución? 4 minutos, 52 segundos. Me desmayé (fíjate: XML + compress = 3 segundos).
enfoque prima
SQL CE Googled un poco, ya pesar de las reclamaciones que aquí: LINQ to SQL (CE) speed versus SqlCe indicando que es en sí SQL CE falta que le di una oportunidad.
El mismo bucle, pero esta vez las inserciones se realizan con SqlCeResultSet (modo DirectTable, consulte: Bulk Insert In SQL Server CE) y SqlCeUpdatableRecord.
¿El resultado? ¿Te sientas cómodamente? Bueno ... 0.3 segundos (¡sí, fracción del segundo!).
El problema
LINQ es muy legible, y las operaciones primas son todo lo contrario. Podría escribir un asignador que traduzca todos los índices de columna a nombres significativos, pero parece que reinventar la rueda, después de todo, ya está hecho en ... LINQ.
¿Entonces tal vez es una forma de decirle a LINQ que acelere las cosas? PREGUNTA - cómo hacerlo?
El código
LINQ
foreach (var entry in dict.Entries.Where(it => it.AlteredByLearning))
{
PrimLibrary.Database.Progress record = null;
record = new PrimLibrary.Database.Progress();
record.Text = entry.Text;
record.Direction = (byte)entry.dir;
db.Progress.InsertOnSubmit(record);
record.Status = (byte)entry.LastLearningInfo.status.Value;
// ... and so on
db.SubmitChanges();
}
operaciones primas
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "Progress"; cmd.CommandType = System.Data.CommandType.TableDirect; SqlCeResultSet rs = cmd.ExecuteResultSet (ResultSetOptions.Updatable);
foreach (var entry in dict.Entries.Where(it => it.AlteredByLearning))
{
SqlCeUpdatableRecord record = null;
record = rs.CreateRecord();
int col = 0;
record.SetString(col++, entry.Text);
record.SetByte(col++,(byte)entry.dir);
record.SetByte(col++,(byte)entry.LastLearningInfo.status.Value);
// ... and so on
rs.Insert(record);
}
¿Puede mostrar algunos ejemplos de código? –
@Kevin Pullin, claro, agregué las partes esenciales para entender cómo hago las inserciones en ambos casos. – greenoldman
¿Has probado ['BinaryFormatter'] (http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx)? – svick