perf(stats): 使用数据库端聚合优化统计查询
This commit is contained in:
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user