Я делаю вызов API, чтобы получить данные (из Geotab), которые я фильтрую, преобразую и вставить в мою БД. Каждая вставка содержит от 1000 до 2000 записей.
Моя таблица в SQL Server 2022 (v16.0.1135.2) выглядит следующим образом:
Код: Выделить всё
CREATE TABLE [dbo].[DiagnosticData]
(
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[DeviceId] [int] NOT NULL,
[DiagnosticId] [int] NOT NULL,
[Value] [float] NOT NULL,
[DateTime] [datetime2](7) NOT NULL,
[UpdateDateTime] [datetime2](7) NOT NULL
)
Код: Выделить всё
public class DiagnosticData
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int64? Id { get; set; }
[Column("DeviceId")]
public int DeviceId { get; set; }
[Column("DiagnosticId")]
public int DiagnosticId { get; set; }
[Required]
public Double Value { get; set; }
[Required]
public DateTime DateTime { get; set; }
[Required]
public DateTime UpdateDateTime { get; set; } = DateTime.UtcNow;
}
ОДИН: Базовый код EF Core:
Код: Выделить всё
public static async Task BulkInsertAsyncEF(IEnumerable entities)
{
await using (PCContext _context = new PCContext())
{
_context.AddRangeAsync(entities);
await _context.SaveChangesAsync();
}
}
Код: Выделить всё
public static async Task BulkInsertSqlAsync(IEnumerable diagnosticData)
{
await using (PCContext _context = new PCContext())
{
StringBuilder sb = new StringBuilder();
foreach (DiagnosticData dd in diagnosticData)
{
sb.Append("INSERT INTO DiagnosticData (DeviceId, DiagnosticId, Value, DateTime, UpdateDateTime) values (");
sb.Append(dd.DeviceId);
sb.Append(',');
sb.Append(dd.DiagnosticId);
sb.Append(',');
sb.Append(dd.Value);
sb.Append(",'");
sb.Append(dd.DateTime.ToString());
sb.AppendLine("',getdate());");
}
await _context.Database.ExecuteSqlRawAsync(sb.ToString());
}
}
Код: Выделить всё
public static async Task BulkInsertAsync(IEnumerable entities)
{
await using (PCContext _context = new PCContext())
{
using var transaction = _context.Database.BeginTransaction();
await _context.BulkInsertAsync(entities, options => { options.IncludeGraph = false; options.PreserveInsertOrder = false; });
transaction.Commit();
}
}
Код: Выделить всё
IEnumerable
diagnosticData = new List();
diagnosticData = statusData.Select(sd => new PC.DiagnosticData()
{
DateTime = sd.DateTime.Value,
DeviceId = devices.First(dv => dv.DeviceId == sd.Device.Id.ToString()).Id,
DiagnosticId = diagnostics.FirstOrDefault(di => di.DiagnosticId == sd.Diagnostic.ToString()).Id,
Value = sd.Data.Value
}
);
// await PC.DiagnosticData.BulkInsertSqlAsync(diagnosticData);
await PC.DiagnosticData.BulkInsertAsync(diagnosticData);
// await PC.DiagnosticData.BulkInsertAsyncEF(diagnosticData);
Код: Выделить всё
statusData
- Метод первый требует от 10 до 15 секунд для вставки ~ 1000 записей, что, по моему мнению, слишком медленно. инстинкт (и эта страница).
- Второй метод был быстрее на ~2 секунды для ~1000 записей (все равно слишком медленно!)
- Третий метод было примерно таким же, как и первый метод.
Я пробовал на двух отдельных экземпляров SQL Server и получил те же результаты (один из них — моя локальная машина разработки без другого трафика)
Учитывая, что первый и третий методы занимают примерно одинаковое количество времени, можно предположить, что это проблема. на уровне EF, но что?
Подробнее здесь: https://stackoverflow.com/questions/792 ... me-but-why