SQL Serverに対して.Net 3.5を使用していくつかのパフォーマンステストを行っています。私は100万レコードを挿入しています。これをトランザクション(直列化可能、RepeatabelReadまたはReadUncommitedのいずれか)内にラップすると、システム上で80秒未満で実行されます。トランザクションを削除すると、約300秒で実行されます。 DBMSは潜在的なロールバックを考慮する必要がないので、トランザクションを使用しないと、データベースに行を挿入する最速の方法になると思います。ここでは何が起きるのですか?これはSQL Server、SQL Server ADO.Net Provider、一般的なADO.Net、一般的なDBMSのための典型的なものですか?1Mレコードの挿入は、トランザクション内ではなく、トランザクション内でより遅いのはなぜですか?
iSeries/DB2データベースの背景があります。 DB2ではコミットメント制御とトランザクションを取得する前にジャーナリングを有効にする必要があり、ジャーナリングは比較的高価です。
私が実際にやりたかったのは、SqlCommandの挿入とvsのEntity Frameworkの挿入を比較したものですが、私はこれらの結果に非常に驚きました。
私はテストを実行するために使用するコードの下にあります。私は以下のコードを実行すると、トランザクションに包まれたすべてのコマンドは(トランザクションが明示的にsettedされていない場合)、暗黙的にあなたが1M取引を持っている、つまりので(AtStartログとAtEndログライン間で測定)約74秒
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
SqlCommand deleteCommand = new SqlCommand("DELETE FROM LockTest");
deleteCommand.Connection = sqlConnection;
deleteCommand.ExecuteNonQuery();
using (SqlTransaction transaction = sqlConnection.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
try
{
if (DEBUG) LOG.Debug("AtStart");
SqlCommand insertCommand = new SqlCommand();
insertCommand.Connection = sqlConnection;
insertCommand.Transaction = transaction;
insertCommand.CommandText = "INSERT INTO LockTest (Id, Name, Description, Type) " +
"VALUES (@id, @name, @description, @type)";
SqlParameter idParameter = new SqlParameter("@id", System.Data.SqlDbType.UniqueIdentifier);
insertCommand.Parameters.Add(idParameter);
SqlParameter nameParameter = new SqlParameter("@name", System.Data.SqlDbType.NVarChar, 50);
insertCommand.Parameters.Add(nameParameter);
SqlParameter descriptionParameter = new SqlParameter("@description", System.Data.SqlDbType.NVarChar, Int32.MaxValue);
insertCommand.Parameters.Add(descriptionParameter);
SqlParameter typeParameter = new SqlParameter("@type", System.Data.SqlDbType.NChar, 20);
insertCommand.Parameters.Add(typeParameter);
insertCommand.Prepare();
for (int i= 0; i < 1000000; i++)
{
Guid g = Guid.NewGuid();
string s = g.ToString();
insertCommand.Parameters["@id"].Value = g;
insertCommand.Parameters["@name"].Value = s;
insertCommand.Parameters["@description"].Value = DateTime.UtcNow.Ticks.ToString();
insertCommand.Parameters["@type"].Value = "test";
insertCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
sqlConnection.Close();
}
if (DEBUG) LOG.Debug("AtEnd");
定義により、トランザクションの分離レベルのみを読み取りに影響します。書き込み(すなわちINSERT)はすべての分離レベルで同じように動作します。 –
実行ごとにテーブルがクリアされますか?一貫して毎回? – gbn
DELETE FROMの代わりにTRUNCATE TABLEを使用して、テストbtwを準備することができます。そして、完全に正確であるためには、毎回ゼロからデータベースを作成し、データとログファイルを事前に拡張して(テストに十分な大きさの初期サイズを割り当てる)確認してください。実行中の1つのデータベースまたはログの増加イベントによって、その実行のすべての結果が破棄されます。 –