programacion - ¿Cuál es la forma más rápida de insertar 100 000 registros en un archivo MDB en C#
lectura y escritura de archivos en c++ (3)
Sé que esta pregunta es bastante general, pero he buscado todo el día y no he podido encontrar la forma adecuada de hacerlo.
Aquí está mi código para insertar unos 100 000 registros ficticios en un archivo MDB utilizando C #.
OleDbConnection con = new OleDbConnection();
string dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;";
string dbSource = "Data Source = D:/programming/sample.mdb";
con.ConnectionString = dbProvider + dbSource;
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandText = "INSERT INTO tblBooks (Title, Price, Tag, Author) VALUES (@title, @price, @tag, @author)";
cmd.Parameters.AddWithValue("@title", "Dummy Text 1");
cmd.Parameters.AddWithValue("@price", 10);
cmd.Parameters.AddWithValue("@tag", "Dummy Text 2");
cmd.Parameters.AddWithValue("@author", "Dummy Text 3");
con.Open();
for (int i = 0; i < 100000; i++)
{
cmd.ExecuteNonQuery();
}
con.Close();
Este código tarda alrededor de un minuto en ejecutarse. ¿Esto es normal? ¿Cuál es la forma correcta de hacerlo más rápido?
Puede usar una tabla de números para agregar varias filas idénticas, por ejemplo:
INSERT INTO aTable ( aText, aNumber )
SELECT @param1 , @param2
FROM Numbers
WHERE Numbers.Number<1000
La tabla de Números es:
Number
0
1
2
<...>
Si ya tiene una "tabla de números" disponible (con al menos 100.000 filas), la respuesta de Remou casi con certeza hará el trabajo más rápido. Probé una prueba rápida en VBA y la consulta
Dim t0 As Single
t0 = Timer
CurrentDb.Execute _
"INSERT INTO tblBooks (Title, Price, Tag, Author) " & _
"SELECT ''Dummy Text 1'', 10, ''Dummy Text 2'', ''Dummy Text 3'' FROM Numbers", _
dbFailOnError
Debug.Print Format(Timer - t0, "0.0") & " seconds"
creó las 100.000 filas en menos de 2 segundos.
Sin embargo, si todavía no tiene una tabla de números, primero deberá crear esa tabla, de modo que si se trata de un requisito de una sola vez, es mejor que optimice su código.
El código tal como se publicó en su pregunta tomó 45 segundos en mi máquina. Dos mejoras que redujeron significativamente el tiempo de ejecución fueron:
Use
.Prepare()
: eso solo redujo el tiempo transcurrido a 16 segundosUtilice una
OleDbTransaction
: Envolver los insertos en una transacción (además de usar.Prepare()
) redujo aún más el tiempo transcurrido a 10 segundos.
El código modificado se ve así:
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
OleDbConnection con = new OleDbConnection();
string dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;";
string dbSource = "Data Source = C:/Users/Gord/Desktop/speed.mdb";
con.ConnectionString = dbProvider + dbSource;
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandText = "INSERT INTO tblBooks (Title, Price, Tag, Author) VALUES (?,?,?,?)";
cmd.Parameters.Add("?", OleDbType.VarWChar, 255);
cmd.Parameters.Add("?", OleDbType.Currency);
cmd.Parameters.Add("?", OleDbType.VarWChar, 255);
cmd.Parameters.Add("?", OleDbType.VarWChar, 255);
cmd.Prepare();
cmd.Parameters[0].Value = "Dummy Text 1";
cmd.Parameters[1].Value = 10;
cmd.Parameters[2].Value = "Dummy Text 2";
cmd.Parameters[3].Value = "Dummy Text 3";
OleDbTransaction trn = con.BeginTransaction();
cmd.Transaction = trn;
for (int i = 0; i < 100000; i++)
{
cmd.ExecuteNonQuery();
}
trn.Commit();
con.Close();
sw.Stop();
Console.WriteLine(String.Format("{0:0.0} seconds", sw.ElapsedMilliseconds / 1000.0));
(Respuesta de bonificación :)
En caso de que alguien se pregunte si OleDbDataAdapter
puede insertar las filas más rápido, parece que no. El siguiente código crea los 100.000 registros ...
var da = new OleDbDataAdapter("SELECT [ID], [Title], [Price], [Tag], [Author] FROM [tblBooks] WHERE False", con);
var cb = new OleDbCommandBuilder(da);
cb.QuotePrefix = "["; cb.QuoteSuffix = "]";
var dt = new System.Data.DataTable();
da.Fill(dt);
for (int i = 0; i < 100000; i++)
{
System.Data.DataRow dr = dt.NewRow();
dr["Title"] = "Dummy Text 1";
dr["Price"] = 10;
dr["Tag"] = "Dummy Text 2";
dr["Author"] = "Dummy Text 3";
dt.Rows.Add(dr);
}
da.Update(dt);
... pero tarda aproximadamente un 30% más en ejecutarse que el código original en la pregunta.