SQLiteトランザクションSQLite複数の文を挿入するのはなぜこんなに遅いのですか.のnet (C#)

8016 ワード

今日ある友达はSQLiteをテストして、それから結論を出しました:SQLiteの効率が低すぎて、大量に1000本の記録を挿入して、意外にも2分かかります!次は彼が送ってくれたテストコードです.めまいがする~~~~~
using System.Data;
using System.Data.Common;
using System.Data.SQLite;

//  
File.Delete("test1.db3");
SQLiteConnection.CreateFile("test1.db3");

DbProviderFactory factory = SQLiteFactory.Instance;
using (DbConnection conn = factory.CreateConnection())
{
  //  
  conn.ConnectionString = "Data Source=test1.db3";
  conn.Open();

  //  
  string sql = "create table [test1] ([id] INTEGER PRIMARY KEY, [s] TEXT COLLATE NOCASE)";
  DbCommand cmd = conn.CreateCommand();
  cmd.Connection = conn;
  cmd.CommandText = sql;
  cmd.ExecuteNonQuery();

  //  
  cmd.Parameters.Add(cmd.CreateParameter());
  
  //  
  Stopwatch watch = new Stopwatch();
  watch.Start();
  
  //  1000 
  for (int i = 0; i < 1000; i++)
  {
    cmd.CommandText = "insert into [test1] ([s]) values (?)";
    cmd.Parameters[0].Value = i.ToString();

    cmd.ExecuteNonQuery();
  }

  //  
  watch.Stop();
  Console.WriteLine(watch.Elapsed);
}

あ~~~~~~~常識的なエラーで、コードを何行か追加しました(新しいコードタグ「//<------------------------」).
using System.Data;
using System.Data.Common;
using System.Data.SQLite;

//  
File.Delete("test1.db3");
SQLiteConnection.CreateFile("test1.db3");

DbProviderFactory factory = SQLiteFactory.Instance;
using (DbConnection conn = factory.CreateConnection())
{
  //  
  conn.ConnectionString = "Data Source=test1.db3";
  conn.Open();

  //  
  string sql = "create table [test1] ([id] INTEGER PRIMARY KEY, [s] TEXT COLLATE NOCASE)";
  DbCommand cmd = conn.CreateCommand();
  cmd.Connection = conn;
  cmd.CommandText = sql;
  cmd.ExecuteNonQuery();

  //  
  cmd.Parameters.Add(cmd.CreateParameter());
  
  //  
  Stopwatch watch = new Stopwatch();
  watch.Start();
  
  DbTransaction trans = conn.BeginTransaction(); // <-------------------
  try 
  {
    //  1000 
    for (int i = 0; i < 1000; i++)
    {
      cmd.CommandText = "insert into [test1] ([s]) values (?)";
      cmd.Parameters[0].Value = i.ToString();

      cmd.ExecuteNonQuery();
    }

    trans.Commit(); // <-------------------
  }
  catch
  {
    trans.Rollback(); // <-------------------
    throw; // <-------------------
  }

  //  
  watch.Stop();
  Console.WriteLine(watch.Elapsed);
}

実行に0.2秒かかります.この差は大きすぎるのではないでしょうか.なぜ単純にトランザクションを有効にするだけでこんなに大きな差があるのでしょうか.簡単です.SQLiteはデフォルトで各操作ごとに1つのトランザクションを開始します.元のコードを1000回挿入すると、少なくとも1000のトランザクションがオープンします.「トランザクションオープン+SQL実行+トランザクションクローズ」は自然に多くの時間を費やします.これも、トランザクションの開始後になぜこんなに速いのかを示す原因です.実はこれはデータベースの操作の基本的な常識で、みんなは覚えていて、悪いコードの効率が悪いのは少し半ではありません.