Я делаю некоторые тесты производительности, используя .Net 3.5 против SQL Server. Я делаю вставку 1 миллиона записей. Когда я заключаю это в транзакцию (сериализуемую, RepeatabelRead или ReadUncommited), она выполняется менее чем за 80 секунд в моей системе. Когда я удаляю транзакцию, она выполняется примерно через 300 секунд. Я ожидаю, что использование отсутствия транзакций будет самым быстрым способом вставки строк в базу данных, потому что СУБД не нужно учитывать потенциальный откат. Что здесь происходит? Типично ли это для SQL Server, поставщика SQL Server ADO.Net, ADO.Net в целом, СУБД в целом?
У меня есть опыт работы с базами данных iSeries/DB2. В DB2 вы должны включить ведение журнала, прежде чем сможете получить управление фиксацией и транзакциями, а ведение журнала относительно дорого.
Что я на самом деле хотел сделать, так это сравнить вставки SqlCommand и вставки Entity Framework, но я был настолько удивлен этими результатами, что хотел сначала выяснить, что здесь происходит.
Ниже код, который я использую для запуска теста. Когда я запускаю приведенный ниже код, это занимает около 74 секунд (измеряется между строками журнала AtStart и строками журнала AtEnd).
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");