.NET Core 3.1优化:TravelPort API数据库存储耗时过长求助
优化EF Core SaveChangesAsync写入日志的性能方案
减少数据库写入的数据量
你代码里已经生成了reqFileName和resFileName,说明请求/响应内容已经存储到文件系统。没必要在数据库里重复存储完整JSON字符串,只需把文件路径存入数据库即可。这样写入数据量会大幅减少,直接解决大字段写入缓慢的问题。使用独立DbContext实例处理日志写入
不要复用业务逻辑的DbContext写日志,单独创建新的DbContext实例专门处理日志操作。业务上下文可能追踪了大量实体,SaveChanges时会遍历所有追踪对象,导致耗时增加。独立上下文只处理当前日志实体,能大幅提升写入速度:// 单独创建日志专用上下文实例 using var logContext = new YourLogDbContext(); await logContext.Logs.AddAsync(new Log() { RequestPath = reqFileName, // 存储文件路径而非完整JSON ResponsePath = resFileName, RequestType = "Air_Seat_Map", Success = true, }); await logContext.SaveChangesAsync();优化JSON序列化开销
如果必须存储JSON字符串,可通过以下方式优化序列化过程:- 复用
JsonSerializerOptions实例,避免每次序列化都创建新实例,减少内存分配 - 对大对象使用异步序列化,减少主线程阻塞:
// 提前定义复用的序列化配置 private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions() { WriteIndented = false, // 关闭格式化进一步缩小体积 IgnoreNullValues = true }; // 异步序列化 var reqJson = await JsonSerializer.SerializeAsync(seatMapReq, _serializerOptions); var resJson = await JsonSerializer.SerializeAsync(res.SeatMapRsp, _serializerOptions); - 考虑换用更高效的序列化库(如MessagePack),序列化速度比System.Text.Json更快,生成的内容体积更小。
- 复用
绕过EF Core追踪,直接执行原生SQL
日志写入是简单插入操作,不需要EF的实体追踪和验证逻辑,直接用原生SQL插入能跳过EF的额外开销:var sql = @"INSERT INTO Logs (Request, Response, ReqFileName, ResFileName, RequestType, Success) VALUES (@Request, @Response, @ReqFileName, @ResFileName, @RequestType, @Success)"; await context.Database.ExecuteSqlRawAsync(sql, new SqlParameter("@Request", JsonSerializer.Serialize(seatMapReq)), new SqlParameter("@Response", JsonSerializer.Serialize(res.SeatMapRsp)), new SqlParameter("@ReqFileName", reqFileName), new SqlParameter("@ResFileName", resFileName), new SqlParameter("@RequestType", "Air_Seat_Map"), new SqlParameter("@Success", true));检查数据库表结构与索引
- 确保
Logs表没有不必要的索引,过多索引会增加写入耗时 - 对于
Request和Response这类大文本字段,使用合适的字段类型(如SQL Server的NVARCHAR(MAX)、MySQL的LONGTEXT),避免因字段类型不匹配导致的隐式转换或存储开销
- 确保
优化DbContext配置
- 对日志专用DbContext禁用实体追踪(
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking),减少内存开销和追踪逻辑 - 检查数据库连接池配置,确保连接字符串中
Max Pool Size设置合理,避免因连接等待导致的耗时
- 对日志专用DbContext禁用实体追踪(
内容的提问来源于stack exchange,提问作者hanushi-thana
相关产品推荐
相关产品推荐

