Uwakpeter Ответов: 1

Пакетная вставка Sqlite становится медленнее после развертывания на клиентской машине


У меня есть приложение C# windows, иногда приложение будет использоваться для импорта записей из файла excel, я мог бы импортировать 2500 записей за одну минуту с помощью пакетной вставки на моей машине разработки, когда я попробовал обычный подход регулярной вставки, это также заняло ту же одну минуту, чтобы вставить 2500 записей, это становится хуже после того, как я развернул приложение и установил его на машине клиента, потребовалось более двух часов, чтобы импортировать такое же количество записей, я просто чувствовал, что так как я использую массовую вставку, скорость должна быть значительно оптимизирована, ниже приведен мой код:

Что я уже пробовал:

public int InsertTaxRecordBatchTransaction(IEnumerable<EmployeeDetails> employeeDetails)
       {
           SQLiteConnection conn = null;
           SQLiteCommand cmd = null;
           var results = new List<int>();

           try
           {
               string insert = "INSERT INTO IncomeTax (OrganisationId,OrganisationName,StaffId,StaffName,Department,Position,NoOfMonthsWorked,TaxIdNumber,SessionId,Month,Year,BasicSalaryVALUES (@OrganisationId,@OrganisationName,@StaffId,@StaffName,@Department,@Position,@NoOfMonthsWorked,@TaxIdNumber,@SessionId,@Month,@Year,@BasicSalary);";
               using (conn = new SQLiteConnection(connstring))
               {
                   conn.Open();
                   using (var transaction = conn.BeginTransaction())
                   {
                       try
                       {
                           using (cmd = conn.CreateCommand())
                           {
                               //cmd = new SQLiteCommand(insert, conn);
                               cmd.CommandType = CommandType.Text;
                               cmd.CommandText = insert;
                               cmd.CommandTimeout = 900000000;
                               cmd.Parameters.Add("@OrganisationId", DbType.String, 50).Value = OrganisationId;
                               cmd.Parameters.Add("@OrganisationName", DbType.String, 50).Value = OrganisationName;
                               cmd.Parameters.Add("@StaffID", DbType.String, 50).Value = StaffId;
                               cmd.Parameters.Add("@StaffName", DbType.String, 50).Value = StaffName;
                               cmd.Parameters.Add("@Department", DbType.String, 50).Value = Department;
                               cmd.Parameters.Add("@Position", DbType.String, 50).Value = Position;
                               cmd.Parameters.Add("@NoOfMonthsWorked", DbType.Int16, 5).Value = NoOfMonthsWorked;
                               cmd.Parameters.Add("@TaxIdNumber", DbType.String, 5).Value = TaxIdNumber;
                               cmd.Parameters.Add("@SessionId", DbType.String, 20).Value = SessionId;
                               cmd.Parameters.Add("@Month", DbType.String, 20).Value = Month;
                               cmd.Parameters.Add("@Year", DbType.String, 20).Value = Year;
                               cmd.Parameters.Add("@BasicSalary", DbType.Decimal, 2).Value = BasicSalary;

                               foreach (var employee in employeeDetails)
                               {
                                   cmd.Parameters.Add("@OrganisationId", DbType.String, 50).Value = employee.OrganisationId;
                                   cmd.Parameters.Add("@OrganisationName", DbType.String, 50).Value = employee.OrganisationName;
                                   cmd.Parameters.Add("@StaffID", DbType.String, 50).Value = employee.StaffId;
                                   cmd.Parameters.Add("@StaffName", DbType.String, 50).Value = employee.StaffName;
                                   cmd.Parameters.Add("@Department", DbType.String, 50).Value = employee.Department;
                                   cmd.Parameters.Add("@Position", DbType.String, 50).Value = employee.Position;
                                   cmd.Parameters.Add("@NoOfMonthsWorked", DbType.Int16, 5).Value = employee.NoOfMonthsWorked;
                                   cmd.Parameters.Add("@TaxIdNumber", DbType.String, 5).Value = employee.TaxIdNumber;
                                   cmd.Parameters.Add("@SessionId", DbType.String, 20).Value = employee.SessionId;
                                   cmd.Parameters.Add("@Month", DbType.String, 20).Value = employee.Month;
                                   cmd.Parameters.Add("@Year", DbType.String, 20).Value = employee.Year;
                                   cmd.Parameters.Add("@BasicSalary", DbType.Decimal, 2).Value = employee.BasicSalary;

                                   results.Add(cmd.ExecuteNonQuery());
                               }

                           }
                           transaction.Commit();
                           DspMsg = "Tax computed successfully!";
                       }
                       catch(Exception ex)
                       {
                           transaction.Rollback();
                           DspMsg = ex.Message+ " some errors have occured, no record was saved! ";
                       }
                   }
               }
              // conn.Close();
           }
           catch (SQLiteException ex)
           {

               DspMsg = ex.Message;
           }
           return results.Sum();
       }

[no name]

И вы ожидаете, что мы сможем объяснить вам, почему один компьютер работает медленнее другого?

Uwakpeter

я также установил на свою систему для тестирования, это также заняло много времени(те же два часа, что и на других машинах), но моя машина dev даже ниже по характеристикам, чем клиентская машина. поэтому я думаю, что речь идет о спецификации системы

1 Ответов

Рейтинг:
4

Dave Kreskowiak

Я удивлен, что код вообще сработал. Вы добавляете новые объекты параметров к объекту команды, который вы перерабатываете на каждой итерации этого цикла. Итак, на момент выполнения запроса у вас есть 12 параметров. В конце второй итерации 24 параметра, 36 параметров, ... В конце 2500 записей у вас есть 30 000 параметров.

Вы уже создали объекты параметров перед циклом. Жаль, что вы не используете их повторно. Это сделало бы код намного быстрее.


Uwakpeter

Я впервые использую транзакцию на sqlite, я исследовал и получил это решение в проекте кода, и решение было помечено как ответ (https://www.codeproject.com/Articles/853842/Csharp-Avoiding-Performance-Issues-with-Inserts-in), в любом случае я буду признателен, если вы будете немного более ясны, чтобы я мог сделать необходимые исправления. Спасибо

Dave Kreskowiak

Вам нужно вернуться назад и поближе взглянуть на код в этой статье. В своем цикле вы добавляете новые объекты параметров в коллекцию параметров команд:

    cmd.Parameters.Add("@OrganisationId", DbType.String, 50).Value = employee.OrganisationId;

Вам нужно повторно использовать существующие объекты параметров внутри вашего цикла:
    cmd.Parameters["@OrganisationId"].Value = employee.OrganisationId;

Uwakpeter

Отличный ответ, он работает, спасибо Дэйву. Теперь я могу пакетно вставить 10 000 записей за 30 секунд, это было здорово.