refactor: optimize statistics retrieval by introducing a method to fetch current and previous records in a single query, reducing database load and improving performance
This commit is contained in:
@@ -1303,28 +1303,33 @@ class Statistics extends Component
|
||||
public function getHistoricalComparisonProperty()
|
||||
{
|
||||
try {
|
||||
// Get current period statistics
|
||||
$currentStats = $this->getStatisticsForPeriod($this->currentPeriod, $this->currentCustomDate);
|
||||
// Get current period statistics with its previous record (for rate calculation)
|
||||
$currentStats = $this->getStatisticsForPeriodWithPrevious($this->currentPeriod, $this->currentCustomDate);
|
||||
|
||||
// Get historical period statistics
|
||||
$historicalStats = $this->getStatisticsForPeriod($this->historicalPeriod, $this->historicalCustomDate);
|
||||
// Get historical period statistics with its previous record
|
||||
$historicalStats = $this->getStatisticsForPeriodWithPrevious($this->historicalPeriod, $this->historicalCustomDate);
|
||||
|
||||
if (!$currentStats || !$historicalStats) {
|
||||
if (!$currentStats || !$historicalStats || !$currentStats['stat'] || !$historicalStats['stat']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$current = $currentStats['stat'];
|
||||
$historical = $historicalStats['stat'];
|
||||
$currentPrevious = $currentStats['previous'];
|
||||
$historicalPrevious = $historicalStats['previous'];
|
||||
|
||||
// Calculate differences and percentages
|
||||
$comparison = [
|
||||
'current' => $currentStats,
|
||||
'historical' => $historicalStats,
|
||||
'current' => $current,
|
||||
'historical' => $historical,
|
||||
'differences' => [
|
||||
'cpu' => $this->calculateDifference($currentStats->cpuused, $currentStats->cpumax, $historicalStats->cpuused, $historicalStats->cpumax),
|
||||
'memory' => $this->calculateDifference($currentStats->memoryused, $currentStats->memorymax, $historicalStats->memoryused, $historicalStats->memorymax),
|
||||
'disk' => $this->calculateDifference($currentStats->diskused ?? 0, $currentStats->diskmax ?? 0, $historicalStats->diskused ?? 0, $historicalStats->diskmax ?? 0),
|
||||
'network_in' => $this->calculateRateDifference($currentStats, $historicalStats, 'netin'),
|
||||
'network_out' => $this->calculateRateDifference($currentStats, $historicalStats, 'netout'),
|
||||
'disk_read' => $this->calculateRateDifference($currentStats, $historicalStats, 'diskread'),
|
||||
'disk_write' => $this->calculateRateDifference($currentStats, $historicalStats, 'diskwrite'),
|
||||
'cpu' => $this->calculateDifference($current->cpuused, $current->cpumax, $historical->cpuused, $historical->cpumax),
|
||||
'memory' => $this->calculateDifference($current->memoryused, $current->memorymax, $historical->memoryused, $historical->memorymax),
|
||||
'disk' => $this->calculateDifference($current->diskused ?? 0, $current->diskmax ?? 0, $historical->diskused ?? 0, $historical->diskmax ?? 0),
|
||||
'network_in' => $this->calculateRateDifferenceOptimized($current, $historical, $currentPrevious, $historicalPrevious, 'netin'),
|
||||
'network_out' => $this->calculateRateDifferenceOptimized($current, $historical, $currentPrevious, $historicalPrevious, 'netout'),
|
||||
'disk_read' => $this->calculateRateDifferenceOptimized($current, $historical, $currentPrevious, $historicalPrevious, 'diskread'),
|
||||
'disk_write' => $this->calculateRateDifferenceOptimized($current, $historical, $currentPrevious, $historicalPrevious, 'diskwrite'),
|
||||
],
|
||||
];
|
||||
|
||||
@@ -1335,6 +1340,30 @@ class Statistics extends Component
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics for a period along with the previous record (for rate calculation)
|
||||
* This reduces queries from 10+ to just 4 total
|
||||
*/
|
||||
protected function getStatisticsForPeriodWithPrevious(string $period, ?string $customDate = null): ?array
|
||||
{
|
||||
$stat = $this->getStatisticsForPeriod($period, $customDate);
|
||||
|
||||
if (!$stat) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the previous record for rate calculation
|
||||
$previous = ServerStatistics::where('server_id', $this->server->id)
|
||||
->where('DateTime', '<', $stat->DateTime)
|
||||
->orderBy('DateTime', 'desc')
|
||||
->first();
|
||||
|
||||
return [
|
||||
'stat' => $stat,
|
||||
'previous' => $previous,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getStatisticsForPeriod(string $period, ?string $customDate = null)
|
||||
{
|
||||
$now = now();
|
||||
@@ -1385,13 +1414,32 @@ class Statistics extends Component
|
||||
|
||||
if ($targetTime) {
|
||||
// Find the statistic closest to the target time (within 30 minutes)
|
||||
return ServerStatistics::where('server_id', $this->server->id)
|
||||
->whereBetween('DateTime', [
|
||||
$targetTime->copy()->subMinutes(30),
|
||||
$targetTime->copy()->addMinutes(30)
|
||||
])
|
||||
->orderByRaw('ABS(TIMESTAMPDIFF(MINUTE, DateTime, ?))', [$targetTime])
|
||||
->first();
|
||||
// Use database-agnostic approach
|
||||
$minTime = $targetTime->copy()->subMinutes(30);
|
||||
$maxTime = $targetTime->copy()->addMinutes(30);
|
||||
|
||||
$stats = ServerStatistics::where('server_id', $this->server->id)
|
||||
->whereBetween('DateTime', [$minTime, $maxTime])
|
||||
->orderBy('DateTime', 'asc')
|
||||
->get();
|
||||
|
||||
if ($stats->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the closest one to target time (database-agnostic)
|
||||
$closest = null;
|
||||
$smallestDiff = PHP_INT_MAX;
|
||||
|
||||
foreach ($stats as $stat) {
|
||||
$diff = abs($stat->DateTime->diffInSeconds($targetTime));
|
||||
if ($diff < $smallestDiff) {
|
||||
$smallestDiff = $diff;
|
||||
$closest = $stat;
|
||||
}
|
||||
}
|
||||
|
||||
return $closest;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -1417,23 +1465,16 @@ class Statistics extends Component
|
||||
];
|
||||
}
|
||||
|
||||
protected function calculateRateDifference($currentStat, $historicalStat, $field)
|
||||
/**
|
||||
* Calculate rate difference using pre-fetched previous stats (optimized)
|
||||
* This eliminates N+1 queries - previous stats are fetched once per period
|
||||
*/
|
||||
protected function calculateRateDifferenceOptimized($currentStat, $historicalStat, $currentPrevious, $historicalPrevious, $field)
|
||||
{
|
||||
// Get previous stats to calculate rates
|
||||
$currentPrevious = ServerStatistics::where('server_id', $this->server->id)
|
||||
->where('DateTime', '<', $currentStat->DateTime)
|
||||
->orderBy('DateTime', 'desc')
|
||||
->first();
|
||||
|
||||
$historicalPrevious = ServerStatistics::where('server_id', $this->server->id)
|
||||
->where('DateTime', '<', $historicalStat->DateTime)
|
||||
->orderBy('DateTime', 'desc')
|
||||
->first();
|
||||
|
||||
$currentRate = 0;
|
||||
$historicalRate = 0;
|
||||
|
||||
if ($currentPrevious) {
|
||||
if ($currentPrevious && $currentStat) {
|
||||
$timeDiff = $currentStat->DateTime->diffInSeconds($currentPrevious->DateTime);
|
||||
if ($timeDiff > 0) {
|
||||
$currentDiff = max(0, ($currentStat->$field ?? 0) - ($currentPrevious->$field ?? 0));
|
||||
@@ -1441,7 +1482,7 @@ class Statistics extends Component
|
||||
}
|
||||
}
|
||||
|
||||
if ($historicalPrevious) {
|
||||
if ($historicalPrevious && $historicalStat) {
|
||||
$timeDiff = $historicalStat->DateTime->diffInSeconds($historicalPrevious->DateTime);
|
||||
if ($timeDiff > 0) {
|
||||
$historicalDiff = max(0, ($historicalStat->$field ?? 0) - ($historicalPrevious->$field ?? 0));
|
||||
@@ -1460,6 +1501,25 @@ class Statistics extends Component
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use calculateRateDifferenceOptimized instead
|
||||
*/
|
||||
protected function calculateRateDifference($currentStat, $historicalStat, $field)
|
||||
{
|
||||
// Get previous stats to calculate rates
|
||||
$currentPrevious = ServerStatistics::where('server_id', $this->server->id)
|
||||
->where('DateTime', '<', $currentStat->DateTime)
|
||||
->orderBy('DateTime', 'desc')
|
||||
->first();
|
||||
|
||||
$historicalPrevious = ServerStatistics::where('server_id', $this->server->id)
|
||||
->where('DateTime', '<', $historicalStat->DateTime)
|
||||
->orderBy('DateTime', 'desc')
|
||||
->first();
|
||||
|
||||
return $this->calculateRateDifferenceOptimized($currentStat, $historicalStat, $currentPrevious, $historicalPrevious, $field);
|
||||
}
|
||||
|
||||
public function getHistoricalComparisonExportDataProperty()
|
||||
{
|
||||
$comparison = $this->historicalComparison;
|
||||
|
||||
Reference in New Issue
Block a user