Wie Roblox Theta Sketches nutzte, um die Creator-Analytik zu skalieren

Analysen sind für heutige Echtzeit-Multiplayer-Spiele unverzichtbar. Bei Roblox konzentrieren wir uns auf die Entwicklung von Messwerkzeugen, die unseren Entwicklern zum Erfolg verhelfen. Unsere kostenlosen, sofort einsatzbereiten Analysen bieten Entwicklern sofortige Einblicke in das Wachstum ihrer Erlebnisse, die Nutzerakquise und die Nutzerbindung und helfen ihnen so, ihren Erfolg zu maximieren.
Der Aufbau der aktuellen Analysesysteme, auf die sich Millionen von Roblox-Entwicklern verlassen, ist eine große Herausforderung. Um diese zu bewältigen, haben wir unsere Analyse-Abfrage-Engine so optimiert, dass ein Cluster mit 120 Prozessorkernen täglich mehr als 6 Millionen Abfragen von etwa 300.000 Besuchern bearbeiten kann, die auf 86 TB Daten zugreifen. Das Herzstück unserer Lösung ist eine OLAP-Datenbank (Online Analytical Processing), die wir aufgrund ihrer Skalierbarkeit und der Integration mit Approximationsalgorithmen ausgewählt haben. Durch eine Kombination aus Daten-Rollup-Techniken sowie HyperLogLog- und Theta-Sketch-Algorithmen stellen wir Analysen für Millionen von Roblox-Erlebnissen bereit1.
Eine Einführung in OLAP-Analysen
Je mehr Daten abgefragt werden, desto länger dauert es, bis Ergebnisse vorliegen. Wenn wir die benötigten Datenmengen reduzieren und den Analyseprozess beschleunigen können, erhalten die Ersteller nahezu in Echtzeit Einblicke in ihre Aktivitäten. Zu den von uns eingesetzten Techniken gehören:
- Spaltenorientierte Speicherung: Das OLAP-System Druid liest nur die erforderlichen Spalten.
- Partitions- und Sortierfilter: Das OLAP liest nur relevante Dateien, die direkt auf die benötigten Datenblöcke verweisen.
- Rollup: Das OLAP aggregiert Ereignisse teilweise anhand gemeinsamer Gruppierungen.
Insbesondere Rollups ermöglichen es OLAPs, zwischen den größten SQL-Abfrage-Engines wie Spark oder Presto (mit Latenzen von mehreren zehn Sekunden) und Punktabfragen oder eingeschränktem SQL zu agieren, die in der Regel vollständig aggregierte Daten liefern. Mit Rollups werden Abfragen nach Dimensionen gruppiert, was zu einer erheblichen Reduzierung der Gesamtzeilenanzahl führt. Bei der Betrachtung von Milliarden oder sogar Billionen von Rohereignissen kann es wesentlich effizienter sein, diese zu Millionen von Gruppierungen zusammenzufassen, die mit einer Latenz von weniger als einer Sekunde aggregiert werden können. Zum Beispiel:

Während Rollups die oben genannten Vorteile der Reduktion bieten, sind bestimmte Metriken dagegen resistent, darunter Abfragen, die eine vollständige Sortierung der Rohdaten erfordern, wie z. B. Distinct-Zählungen, Perzentile und Häufigkeitsabfragen.
Glücklicherweise können wir diese Einschränkungen mit Techniken umgehen, die ein statistisch begrenztes Näherungsergebnis zurückgeben, das auf komplexen Datenstrukturen basiert, die eine Stichprobe des gesamten Datensatzes enthalten. Diese Datenstrukturen sind für den Einsatz in Rollup-Techniken konzipiert und kombinieren zwei Distinct-Counts über eine Vereinigungsoperation, ähnlich wie beim Addieren zweier Zahlen.
Aufschlüsselung der Arbeitslasten bei Roblox Analytics
Bei Roblox stellen wir Creators ein zentrales Dashboard zur Verfügung, in dem sie ihre wichtigsten Kennzahlen finden. Dazu gehören:
- Engagement: täglich aktive Nutzer (DAU), monatlich aktive Nutzer (MAU), Kundenbindung und Trichter
- Monetarisierung: Umsatz, durchschnittlicher Umsatz pro Nutzer, Verkäufe und Wirtschaft
- Akquisitionsdaten
- Personalisierung von Miniaturansichten und Versuchsergebnisse
- Analysen zu Empfehlungen auf der Startseite
- Und vieles mehr.

Auswahl und Optimierung der Suchmaschine
Bewältigung von Leistungsherausforderungen
In einer abschließenden Runde von Produktions-Shadow-Tests stießen wir auf eine wichtige Herausforderung: Die Leistung unserer MAU-Abfragen musste verbessert werden, nachdem wir von einzelnen großen Abfragen auf tägliche Aggregationsmuster umgestellt hatten. Diese sind für unsere Visualisierungen der Creator-Analysen von entscheidender Bedeutung.
Wir stellten fest, dass die Struktur der Abfrage die zugrunde liegende Leistung unserer OLAP-Lösung stark beeinflusste. Standardabfragen mit mehreren Ausführungsstufen (wie verschachtelte „GROUP BY“-Anweisungen2) verlagern oft große Teile der Arbeit auf die leichtgewichtigen Broker-Knoten.
Dies ist ein klassisches Big-Data-Problem, bei dem ein Teil einer Abfrage letztendlich auf wichtigen kleinen Servierknoten ausgeführt wird. Wir gingen davon aus, dass unsere approximativen Datenstrukturen wie einfache Zählungen oder Summen funktionieren würden, stellten jedoch fest, dass sie sich tatsächlich ganz anders verhielten.
Die folgende Abbildung veranschaulicht das Problem. Sie zeigt, wie unsere historischen Knoten eine Teilaggregation durchführten, indem sie für jeden Tag einen Theta-Sketch zusammenfassten und ihre Daten dann an den Broker zurücksendeten. Der Broker versuchte dann, jeden großen täglichen Sketch zu einem einzigen Monatswert pro Tag zusammenzufassen. Bei 30 Tagen MAU bedeutete dies, 1.800 Theta-Sketches mit maximaler Größe auf einem Broker zusammenzuführen, was zu einer langsameren, fehleranfälligen Abfrage führte, die die Broker-CPU monopolisierte.

Unsere Lösung bestand darin, das OLAP mit weniger großen historischen Workern auszuführen, um die Datenlokalität für Datenquellen zu maximieren, die auf Approximationsabfragen beruhten. In der Praxis führte dies dazu, dass eine Merge-Operation, die mehr als 100 MB Datenverarbeitung hätte erfordern können, zurück auf unsere historischen Knoten verlagert wurde.
Um dies in SQL zu erreichen, verwendeten wir einen Inline-Join, damit Abfragen die erforderlichen Informationen an historische Knoten weiterleiten, und erstellten eine Abfrage mit einer Liste von Inline-Ergebnisdaten. Jedes Ergebnisdatum kann dann die relevanten Daten aus den historischen Knotensegmenten abrufen. Die Daten werden anschließend an den Broker zurückgegeben, wo die Ergebnisse schnell zu einer einzigen Zuordnung von Ergebnisdaten zu Metrikdaten zusammengeführt werden, wie unten dargestellt.

Diese Optimierung hatte dramatische Auswirkungen auf die Leistung bei groß angelegten Abfragen. Bei der Aufschlüsselung der monatlichen aktiven Nutzer (MAU) einer großen Anwendung nach Ländern verbesserte sich die durchschnittliche Abfrageleistung um das Fünffache (von 17,53 Sekunden auf 3,23), wie in der folgenden Grafik dargestellt. Außerdem konnten wir eine 50-fache Reduzierung der CPU-Zeit auf dem Broker feststellen (von 16,83 Sekunden auf 0,34).
Auch wenn die Ergebnisse variieren, unterstreicht dies, wie wichtig es ist, komplexe Operationen (wie das Zusammenführen von Millionen von Skizzen) mit Sorgfalt zu behandeln. Die Annahme, dass diese Operationen einfachen Aggregationen entsprechen, kann zu erheblichen Leistungsproblemen führen, insbesondere auf Systemen, auf denen Last-Mile-Client-Aggregationen üblich sind.
Rollups und ein theoretischer Theta-Würfel

Wir haben außerdem einen Theta-Kubus untersucht, also einen verallgemeinerten Ansatz, um die Lücke zwischen einfachen Rollup-Tabellen und vollständig rohen Tabellen durch ungefähre Schnittmengen von Mengen zu schließen. Dieser Ansatz behebt eine grundlegende Einschränkung: Rollup-Tabellen verlieren ihren Vorteil, wenn Abfragen viele Ebenen von Dimensionen mit hoher Kardinalität abdecken müssen. Das liegt daran, dass jede Dimension dazu führt, dass die Rollup-Kardinalität mit ∏dim (Produkt der Dimensionen) skaliert.
Wir haben ein System entworfen, das nach gemeinsamen Dimensionsgruppen mit einer Kardinalitätsbegrenzung aggregiert, was Rollup-Leistungsabfragen für alles in der Gruppe ermöglicht. Bei der Suche nach Kombinationen von Dimensionen über Gruppen hinweg würden wir dann einen approximativen Join4 über die Mengen hinweg versuchen und die Metrikergebnisse zusammen mit Fehlerschätzungen zurückgeben. Eine Abfrage mit hohem geschätztem Fehler würde an eine Rohdatentabelle weitergeleitet, wo die vielen Filter umfangreiche Pushdown-Optimierungen ermöglichen sollten.


Da wir diese Fehlerquote schnell berechnen können, dient sie auch als starkes Indiz dafür, dass das Lesen der Rohdatentabelle wahrscheinlich performant sein wird. In Fällen, in denen die überlappenden Daten im Verhältnis zur Vereinigung gering sind (z. B. Japanischsprachige in Deutschland), wird eine große Anzahl der Zeilen der Rohdatentabelle herausgefiltert. Dies führt zu effizienten Pushdown-Optimierungen. Ein System, das Dimensionsgruppen, approximative Joins und fehlerbasierte Rohdatentabellen-Lesevorgänge nutzt, würde die Rollup-Leistung bei approximationsfreundlichen Abfragen wirklich maximieren.
Für Roblox wird diese Lösung eher auf unserer nächsten Skalierungsstufe anwendbar sein – möglicherweise für dynamische Trichter- oder benutzerdefinierte Ereignisanalysen –, während unsere derzeitige einfache Rollup-Replik die heutigen Anforderungen erfüllt.
Aufbau einer Self-Service-Plattform
Nachdem wir unseren Broker optimiert hatten, wandten wir uns der Entwicklung von Tools für das Onboarding und die Abfrage von Datensätzen zu, die unserer OLAP-Lösung hinzugefügt wurden. Wir erstellten eine Open-Source-Bibliothek für Spark und Trino UDAF für unsere Datasketch-Funktionen, wodurch Spark dasselbe binäre Datasketch-Format wie unser OLAP6 verwenden kann. Dadurch blieb der Großteil unserer Rechenlast in Spark und die Approximation konnte unternehmensweit standardisiert werden, was bei bestimmten Datensätzen zu einer potenziellen Senkung der Rechenkosten um bis zu 80 % führte.
Wir haben das Onboarding durch eine interne Erweiterung unseres Batch-Job-Schedulers vereinfacht und eine API im Dataframe-Stil definiert, die Entwickler bei der Festlegung definitiver Kennzahlen und Dimensionen unterstützt und so die Auswirkungen offener Abfragen reduziert. Außerdem haben wir einige Beispiel-Workflows als Open Source veröffentlicht, die zeigen, wie wir diese Daten in unser OLAP laden und abfragen.
Unsere optimierten Analysedatensätze liefern unseren Creators nun tiefgehende Einblicke. Durch unsere Optimierungen konnten wir die durchschnittliche Leistung um das Vierfache und die Leistung im Worst-Case-Szenario um das 50-Fache verbessern. Die Self-Service-Plattform ermöglicht es unserem Creator Analytics-Team, weiterhin neue Datensätze für Entwickler zu erstellen. Wir freuen uns darauf, zu sehen, wie Entwickler aller Größenordnungen diese Tools nutzen, um unglaubliche Erlebnisse auf Roblox zu schaffen.
1 Berechnet anhand der letzten 60 Tage mit eindeutigen Universen und beliebigen Zugriffen
2 Wie diese einfache MAU-Abfrage
3 Die Ergebnisse stammen vom 21. bis 28. März 2025
4 So ausgeführt: 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 Über eine Druid-SQL-Funktion COMPLEX_DECODE_BASE64('HLLSketch', sketch_col_name ).


