perf(dashboard): economy reports on a large ledger

- Leave staff out of the currency and U-score reports by excluding the few staff characters,
  instead of joining every ledger row to its character and account.
- Top earners: total per character first and look up names for the top rows only.
- The places list and the activity report read map events for every kind in one query
  (GetMapZonesAllKinds) instead of one query per kind.

With about 1M currency rows and 650k map event rows (90 days) on MariaDB: currency 1.8 s to
0.8 s, top earners 2.4 s to 0.75 s, places 2.6 s to 0.5 s, activity 2.6 s to 1.7 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-26 18:55:03 -05:00
parent 98fd72cf75
commit fa3e5de1d9
9 changed files with 45 additions and 15 deletions

View File

@@ -223,10 +223,9 @@ namespace EconomyPlaces {
// Every (zone, clone) with map events or statistics in the range
std::map<std::pair<uint32_t, uint32_t>, PlaceTotals> PlacesWithData(uint32_t from, uint32_t to) {
std::map<std::pair<uint32_t, uint32_t>, PlaceTotals> places;
for (const auto kind : magic_enum::enum_values<IEconomyLedger::eMapEvent>()) {
for (const auto& row : Database::Get()->GetMapZones(kind, from, to)) {
places[{ row.value("zone", 0u), row.value("clone", 0u) }].events += row.value("events", int64_t{ 0 });
}
for (const auto& row : Database::Get()->GetMapZonesAllKinds(from, to)) {
if (!magic_enum::enum_cast<IEconomyLedger::eMapEvent>(row.value("kind", 0))) continue;
places[{ row.value("zone", 0u), row.value("clone", 0u) }].events += row.value("events", int64_t{ 0 });
}
for (const auto& row : Database::Get()->GetPlayerStatsPerZone(from, to, false)) {
places[{ row.value("zone", 0u), row.value("clone", 0u) }].stats += row.value("amount", int64_t{ 0 });

View File

@@ -1025,11 +1025,9 @@ void RegisterReportRoutes() {
auto statRows = Database::Get()->GetPlayerStatsPerZone(from, to, excludeStaff);
nlohmann::json mapRows = nlohmann::json::array();
for (const auto kind : magic_enum::enum_values<IEconomyLedger::eMapEvent>()) {
for (auto& row : Database::Get()->GetMapZones(kind, from, to)) {
row["kind"] = static_cast<int>(kind);
mapRows.push_back(std::move(row));
}
// One pass over the range for every kind (a query per kind read it once each)
for (auto& row : Database::Get()->GetMapZonesAllKinds(from, to)) {
if (magic_enum::enum_cast<IEconomyLedger::eMapEvent>(row.value("kind", 0))) mapRows.push_back(std::move(row));
}
std::set<uint32_t> clones;
for (const auto* rows : { &statRows, &mapRows }) for (const auto& row : *rows) clones.insert(row.value("clone", 0u));