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