perf(stats): 使用数据库端聚合优化统计查询

This commit is contained in:
ssss
2026-07-03 14:28:35 +08:00
parent d3e4b2b8de
commit f771abb6bf

View File

@@ -1,106 +1,120 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using WCTDataMiner.Core.Data; using WCTDataMiner.Core.Data;
using WCTDataMiner.Core.Models; using WCTDataMiner.Core.Models;
namespace WCTDataMiner.Core.Services; namespace WCTDataMiner.Core.Services;
/// <summary> /// <summary>
/// 统计查询服务 /// 统计查询服务 - 使用数据库端聚合优化内存效率
/// </summary> /// </summary>
public class StatsService public class StatsService
{ {
private readonly WctMinerDbContext _context; private readonly WctMinerDbContext _context;
private readonly ILogger<StatsService> _logger;
public StatsService(WctMinerDbContext context) public StatsService(WctMinerDbContext context, ILogger<StatsService> logger)
{ {
_context = context; _context = context;
_logger = logger;
} }
/// <summary> /// <summary>
/// 获取整体统计摘要 /// 获取整体统计摘要(并行查询优化)
/// </summary> /// </summary>
public async Task<StatsSummary> GetSummaryAsync() public async Task<StatsSummary> GetSummaryAsync()
{ {
var scenarioCount = await _context.TestScenarios.CountAsync(); // 使用 Task.WhenAll 并行执行多个查询
var qfodCount = await _context.QfodRecords.CountAsync(); var tasks = new[]
var plossCount = await _context.PlossRecords.CountAsync(); {
var panelCount = await _context.TxPanels.CountAsync(); _context.TestScenarios.CountAsync(),
var hardwareCount = await _context.TxHardwares.CountAsync(); _context.QfodRecords.CountAsync(),
var softwareCount = await _context.TxSoftwares.CountAsync(); _context.PlossRecords.CountAsync(),
var rxTypeCount = await _context.RxTypes.CountAsync(); _context.TxPanels.CountAsync(),
_context.TxHardwares.CountAsync(),
_context.TxSoftwares.CountAsync(),
_context.RxTypes.CountAsync()
};
return new StatsSummary( var results = await Task.WhenAll(tasks);
scenarioCount, qfodCount, plossCount,
panelCount, hardwareCount, softwareCount, rxTypeCount var summary = new StatsSummary(
results[0], results[1], results[2],
results[3], results[4], results[5], results[6]
); );
_logger.LogDebug("统计摘要: Scenarios={ScenarioCount}, Qfod={QfodCount}, Ploss={PlossCount}",
summary.ScenarioCount, summary.QfodCount, summary.PlossCount);
return summary;
} }
/// <summary> /// <summary>
/// 按FOD类型统计Qfod记录 /// 按FOD类型统计Qfod记录(数据库端聚合)
/// </summary> /// </summary>
public async Task<List<FodTypeStats>> GetStatsByFodTypeAsync() public async Task<List<FodTypeStats>> GetStatsByFodTypeAsync()
{ {
// 先加载到内存再分组EF Core 对 GroupBy + 自定义类型有限制) // 使用数据库端 GroupBy
var data = await _context.QfodRecords var stats = await _context.QfodRecords
.Select(r => r.FodType) .GroupBy(r => r.FodType)
.ToListAsync();
return data
.GroupBy(f => f)
.Select(g => new FodTypeStats(g.Key, g.Count())) .Select(g => new FodTypeStats(g.Key, g.Count()))
.OrderBy(s => s.FodType) .OrderBy(s => s.FodType)
.ToList(); .ToListAsync();
_logger.LogDebug("按 FOD 类型统计完成: {Count} 种类型", stats.Count);
return stats;
} }
/// <summary> /// <summary>
/// 按面板类型统计 /// 按面板类型统计(数据库端聚合 - 使用维度表反向统计)
/// </summary> /// </summary>
public async Task<List<DimensionStats>> GetStatsByPanelAsync() public async Task<List<DimensionStats>> GetStatsByPanelAsync()
{ {
var data = await _context.TestScenarios // 方式: 使用维度表反向统计(更高效)
.Include(s => s.TxPanel) var stats = await _context.TxPanels
.Select(s => s.TxPanel.Name) .Select(p => new DimensionStats(
p.Name,
p.TestScenarios.Count()
))
.OrderByDescending(s => s.Count)
.ToListAsync(); .ToListAsync();
return data _logger.LogDebug("按面板类型统计完成: {Count} 种面板", stats.Count);
.GroupBy(n => n) return stats;
.Select(g => new DimensionStats(g.Key, g.Count()))
.OrderByDescending(s => s.Count)
.ToList();
} }
/// <summary> /// <summary>
/// 按硬件版本统计 /// 按硬件版本统计(数据库端聚合)
/// </summary> /// </summary>
public async Task<List<DimensionStats>> GetStatsByHardwareAsync() public async Task<List<DimensionStats>> GetStatsByHardwareAsync()
{ {
var data = await _context.TestScenarios var stats = await _context.TxHardwares
.Include(s => s.TxHardware) .Select(h => new DimensionStats(
.Select(s => s.TxHardware.Version) h.Version,
h.TestScenarios.Count()
))
.OrderByDescending(s => s.Count)
.ToListAsync(); .ToListAsync();
return data _logger.LogDebug("按硬件版本统计完成: {Count} 种版本", stats.Count);
.GroupBy(v => v) return stats;
.Select(g => new DimensionStats(g.Key, g.Count()))
.OrderByDescending(s => s.Count)
.ToList();
} }
/// <summary> /// <summary>
/// 按RX类型统计 /// 按RX类型统计(数据库端聚合)
/// </summary> /// </summary>
public async Task<List<DimensionStats>> GetStatsByRxTypeAsync() public async Task<List<DimensionStats>> GetStatsByRxTypeAsync()
{ {
var data = await _context.TestScenarios var stats = await _context.RxTypes
.Include(s => s.RxType) .Select(r => new DimensionStats(
.Select(s => s.RxType.Name) r.Name,
r.TestScenarios.Count()
))
.OrderByDescending(s => s.Count)
.ToListAsync(); .ToListAsync();
return data _logger.LogDebug("按 RX 类型统计完成: {Count} 种类型", stats.Count);
.GroupBy(n => n) return stats;
.Select(g => new DimensionStats(g.Key, g.Count()))
.OrderByDescending(s => s.Count)
.ToList();
} }
} }