De content op deze site is vertaald met behulp van kunstmatige intelligentie (AI) of machinevertalingstechnologie en kan fouten bevatten.

Skip to content

Hoe Roblox Theta Sketches gebruikte om de analyse van makers op te schalen

SEO image for Roblox Appoints Naveen Chopra as Chief Financial Officer

Analytics zijn essentieel voor de realtime multiplayergames van vandaag. Bij Roblox richten we ons op het ontwikkelen van meetinstrumenten om onze makers te helpen floreren. Onze gratis, kant-en-klare analytics geven makers direct inzicht in de groei, gebruikerswerving en retentie van hun ervaringen, waardoor ze hun succes kunnen maximaliseren. 

Het bouwen van de up-to-date analysesystemen waar miljoenen Roblox-makers op vertrouwen, is een belangrijke uitdaging. Om dit aan te pakken, hebben we onze analysequery-engine geoptimaliseerd, zodat een verwerkingscluster met 120 cores meer dan 6 miljoen queries per dag kan verwerken van ongeveer 300.000 dagelijkse bezoekers die toegang hebben tot 86 TB aan gegevens. De kern van onze oplossing is een OLAP-database (Online Analytical Processing) die we hebben gekozen vanwege de schaalbaarheid en de integratie met benaderingsalgoritmen. Door een combinatie van datarolluptechnieken en HyperLogLog- en Theta Sketch-algoritmen te gebruiken, bieden we analytics voor miljoenen Roblox-ervaringen1

Een inleiding tot OLAP-analyse

Hoe meer gegevens er worden opgevraagd, hoe langer het duurt om resultaten te genereren. Wanneer we de benodigde gegevens kunnen verminderen en het analyseproces kunnen versnellen, kunnen makers bijna realtime inzichten krijgen uit hun acties. Enkele van de technieken die we gebruiken zijn:

  1. Kolomopslag: De OLAP, Druid, leest alleen de benodigde kolommen.
  2. Partitie- en sorteerfilters: De OLAP leest alleen relevante bestanden die direct naar de benodigde gegevensblokken verwijzen.
  3. Rollup: De OLAP aggregeert gebeurtenissen gedeeltelijk met behulp van algemene groeperingen.

Met name rollups stellen OLAP's in staat om te werken tussen de grootste SQL-query-engines, zoals Spark of Presto (met latenties van tientallen seconden), en point query of beperkte SQL, die doorgaans volledig geaggregeerde gegevens leveren. Met rollups worden query's gesorteerd op groeperingen van dimensies, wat resulteert in een aanzienlijke vermindering van de totale rijcardinaliteit. Bij het bekijken van miljarden of zelfs triljoenen ruwe gebeurtenissen kan het veel efficiënter zijn om deze samen te voegen tot miljoenen groeperingen die met een latentie van minder dan een seconde kunnen worden geaggregeerd. Bijvoorbeeld: 

Hoewel rollups de hierboven genoemde voordelen bieden, zijn bepaalde statistieken hier niet gevoelig voor, waaronder query's die een volledige sortering van de ruwe gegevens vereisen, zoals unieke tellingen, percentielen en frequentiequery's.

Gelukkig kunnen we deze beperkingen omzeilen met technieken die een statistisch begrensd benaderend resultaat opleveren op basis van complexe gegevensstructuren die een steekproef van de volledige dataset bevatten. Deze gegevensstructuren zijn ontworpen voor gebruik in rollup-technieken en combineren twee verschillende tellingen via een union-bewerking, vergelijkbaar met het optellen van twee getallen.

Een analyse van de werklast van Roblox Analytics

Bij Roblox bieden we makers een gecentraliseerd dashboard waar ze hun belangrijkste inzichten kunnen vinden. Deze omvatten: 

  • Betrokkenheid: dagelijkse actieve gebruikers (DAU), maandelijkse actieve gebruikers (MAU), retentie en trechters 
  • Monetisatie: omzet, gemiddelde omzet per gebruiker, verkopen en economie
  • Acquisitiegegevens 
  • Personalisatie van thumbnails en experimentresultaten
  • Analyses van aanbevelingen op de startpagina
  • En er komt nog meer aan. 
Bij het bouwen van ons systeem hebben we ons gericht op het optimaliseren van worst-case-query's. Dit zijn doorgaans grote distinct counts (>100 miljoen UUID's), zoals MAU voor populaire ervaringen, die de laadtijden kunnen vertragen van seconden tot minuten. We hebben een statistisch benaderingsraamwerk gebouwd om query's binnen een latentie van twee seconden te houden. We hebben zowel HyperLogLog- als Theta Sketch-technieken uit industriestandaardbibliotheken aangepast, waardoor de worst-case-query's zijn teruggebracht van het lezen van meer dan 100 miljoen rijen naar ongeveer 5 miljoen.
De zoekmachine kiezen en optimaliseren
Nadat we onze OLAP-oplossing hadden geselecteerd, hebben we zes maanden aan engagementgegevens geladen en de prestatielimieten van ons systeem aan een zware test onderworpen. Met ongeveer 100 cores en 500 GB geheugen ontdekten we dat we binnen twee seconden willekeurig 5 miljoen binaire Theta Sketch-objecten (in totaal ongeveer 100 MB) konden samenvoegen. Dit werd gedaan op cold-start-query's die vanaf schijf lazen zonder toegang tot een cache in het geheugen. Netwerkopslagopties zoals S3-leesbewerkingen, die Clickhouse en Duckdb standaard bieden, laten aanzienlijk slechtere prestaties zien. 
Prestatieproblemen overwinnen

Tijdens een laatste ronde van schaduwtesten in de productie ontdekten we een belangrijke uitdaging: de prestaties van onze MAU-query's moesten worden verbeterd na de overstap van enkele grote query's naar dagelijkse aggregatiepatronen. Deze zijn cruciaal voor onze visualisaties van creator analytics. 

We ontdekten dat de structuur van de query een grote invloed had op de onderliggende prestaties van onze OLAP-oplossing. Standaardquery's met meerdere uitvoeringsfasen (zoals geneste "GROUP BY"-instructies2) verplaatsen vaak grote delen van het werk naar de lichtgewicht broker-knooppunten. 

Dit is een klassiek big data-probleem waarbij een deel van een query uiteindelijk wordt uitgevoerd op belangrijke kleine serving-knooppunten. We verwachtten dat onze benaderende gegevensstructuren zouden functioneren als eenvoudige tellingen of sommen, maar we ontdekten dat ze zich in werkelijkheid heel anders gedroegen. 

De onderstaande afbeelding illustreert het probleem. Deze laat zien hoe onze historische knooppunten gedeeltelijke aggregatie zouden uitvoeren, waarbij ze voor elke dag een Theta Sketch samenvatten en vervolgens hun gegevens terugsturen naar de broker. De broker probeerde vervolgens elke grote dagelijkse sketch samen te voegen tot één maandelijkse waarde per dag. Voor 30 dagen MAU betekende dit het samenvoegen van 1.800 Theta Sketches van maximale grootte op een broker, wat resulteerde in een tragere, storingsgevoelige query die de CPU van de broker monopoliseerde. 

Onze oplossing was om de OLAP uit te voeren met minder grote historische workers om de datalocaliteit te maximaliseren voor gegevensbronnen die afhankelijk waren van benaderingsquery's. In de praktijk zorgde dit ervoor dat een samenvoegingsbewerking, die mogelijk meer dan 100 MB aan gegevensverwerking had vereist, terug naar onze historische knooppunten werd gestuurd.

Om dit in SQL te realiseren, gebruikten we een inline join om queries de benodigde informatie naar historische knooppunten te laten doorgeven en stelden we een query op met een lijst van inline resultaatdatums. Elke resultaatdatum kan vervolgens de relevante gegevens verzamelen uit de historische knooppuntsegmenten. De gegevens worden vervolgens teruggestuurd naar de broker, waar de resultaten snel worden samengevoegd tot één kaart van resultaatdatum naar metrische gegevens, zoals hieronder te zien is.

Deze optimalisatie had een enorme impact op de prestaties bij grootschalige zoekopdrachten. Voor de uitsplitsing van de MAU per land van een belangrijke ervaring verbeterden de gemiddelde zoekprestaties met een factor 5 (van 17,53 seconden naar 3,23), zoals te zien is in de onderstaande grafiek. We zagen ook een 50-voudige vermindering van de CPU-tijd op de broker (van 16,83 seconden naar 0,34). 

Hoewel de resultaten variëren, benadrukt dit het belang van het zorgvuldig behandelen van complexe bewerkingen (zoals het samenvoegen van miljoenen schetsen). Aannemen dat deze bewerkingen gelijkwaardig zijn aan eenvoudige aggregaties kan leiden tot aanzienlijke prestatieproblemen, vooral op systemen waar last-mile-clientaggregaties veel voorkomen.

Rollups en een theoretische theta-kubus

De gemiddelde analytische query op ons platform heeft minimale uitsplitsingen en raakt zelden dimensies met een hoge cardinaliteit (zoals land). Met deze kennis hebben we besloten onze data te dupliceren en een rollup-tabel te maken met minder dimensies, die voldoende zou zijn voor meer dan 98%3 van onze queries. Deze presteerde vier keer beter op de gemiddelde query.

We hebben ook een theta-kubus onderzocht, oftewel een algemene aanpak om de kloof tussen basisroll-uptabellen en volledig ruwe tabellen te overbruggen via benaderende setintersecties. Deze aanpak pakt een fundamentele beperking aan: roll-uptabellen verliezen hun voordeel wanneer query's vele lagen van dimensies met hoge cardinaliteit moeten doorlopen. Dat komt doordat elke dimensie ervoor zorgt dat de roll-up-cardinaliteit schaalt als ∏dim (product van dimensies).

We hebben een systeem ontworpen dat zou aggregeren op basis van gemeenschappelijke dimensiegroepen met een cardinaliteitslimiet, waardoor rollup-prestatiequery's op alles in de groep mogelijk worden. Vervolgens, bij het zoeken naar combinaties van dimensies tussen groepen, zouden we een benaderende join4 tussen de sets proberen en de metrische resultaten samen met foutschattingen retourneren. Een query met een hoge geschatte fout zou worden doorgestuurd naar een ruwe tabel, waar de vele filters grote pushdown-optimalisaties mogelijk zouden moeten maken.

Deze theta-kubusbenadering wisselt van dimensionaliteit, wat resulteert in een ∑dim (som van dimensies) uitbreiding voor het aantal rijen in plaats van de ∏dim uitbreiding. Dit kan natuurlijk ten koste gaan van de nauwkeurigheid, een dynamiek die recht evenredig is met de overlappingsgrootte5 tussen de twee dimensiegroepen. De onderliggende reden hiervoor houdt rechtstreeks verband met de manier waarop Theta Sketches een op K-stijl gesorteerde lijst opslaan, wat botsingen tussen twee sets met een hoge inherente overlap zal maximaliseren.

Omdat we dit foutenpercentage snel kunnen berekenen, dient het ook als een sterk signaal dat het lezen van de ruwe tabel waarschijnlijk goed zal presteren. In gevallen waarin overlappende gegevens klein zijn ten opzichte van de unie (bijvoorbeeld Japanssprekenden in Duitsland), zal een groot aantal rijen van de ruwe tabel worden weggefilterd. Dat resulteert in efficiënte pushdown-optimalisaties. Een systeem dat gebruikmaakt van dimensiegroepen, benaderende joins en op fouten gebaseerde ruwe tabelverwerkingen zou de rollup-prestaties bij benaderingsvriendelijke query's echt maximaliseren.

Voor Roblox zal deze oplossing beter toepasbaar zijn op ons volgende schaalniveau – mogelijk voor dynamische trechter- of aangepaste gebeurtenisanalyse – terwijl onze huidige eenvoudige rollup-replica voldoet aan de huidige behoeften.

Een selfserviceplatform opzetten

Nadat we onze broker hadden geoptimaliseerd, richtten we ons op het bouwen van tools voor het onboarden en opvragen van datasets die aan onze OLAP-oplossing waren toegevoegd. We bouwden een open-source Spark- en Trino UDAF-bibliotheek voor onze datasketch-functies, waardoor Spark hetzelfde binaire datasketch-formaat kan gebruiken als onze OLAP6. Hierdoor bleef het grootste deel van onze rekenwerkzaamheden in Spark en konden we de benadering binnen Roblox standaardiseren, waardoor de rekenkosten voor bepaalde datasets mogelijk met wel 80% konden worden verlaagd.

We hebben het onboarden vereenvoudigd met een interne uitbreiding op onze batchjob-planner en een dataframe-achtige API gedefinieerd die ontwikkelaars helpt bij het bepalen van definitieve maatstaven en dimensies, waardoor de impact van open query's wordt verminderd. We hebben ook enkele voorbeeldworkflows open source gemaakt die laten zien hoe we deze gegevens in onze OLAP laden en opvragen.

Onze geoptimaliseerde analytische datasets bieden onze makers nu diepgaande inzichten. Onze optimalisaties hebben de gemiddelde prestaties met een factor 4 verbeterd en de prestaties in het slechtste geval met een factor 50. Dankzij het selfserviceplatform kan ons Creator Analytics-team blijven werken aan nieuwe datasets voor ontwikkelaars. We zijn verheugd om te zien dat ontwikkelaars van elke omvang deze tools gebruiken om ongelooflijke ervaringen op Roblox te creëren.

1 Berekend op basis van de laatste 60 dagen van unieke universums met enige toegang
2 Zoals deze eenvoudige MAU-query
3 Resultaten zijn van 21-28 maart 2025
4 Uitgevoerd als volgt: SELECT c.experience_id, c.country, p.platform, THETA_INTERSECT(c.user_theta, p.user_theta) from (select experience_id, country, user_theta from theta_cube where agg_level = country) c union (select experience_id, platform, user_theta from theta_cube where agg_level = platform) p
5 https://datasketches.apache.org/docs/Theta/ThetaSketchSetOpsAccuracy.html
6 Via een Druid SQL-functie COMPLEX_DECODE_BASE64('HLLSketch', sketch_col_name ).