Architektur & Datenfluss
KickBannerStats wurde entwickelt, um ein spezifisches Problem von High-Traffic-Webseiten zu lösen: Performance bei der Auswertung.
Anstatt Millionen von Rohdaten-Zeilen bei jedem Seitenaufruf neu zu berechnen, nutzt die Komponente einen Data-Warehouse-Ansatz (ETL: Extract, Transform, Load).
1. Das Datenbank-Schema
Die Basis der Performance ist die Entkopplung von Schreib- und Lese-Operationen.
- Schreiben (Joomla Core): Jeder View/Klick landet in
#__banner_tracks. Diese Tabelle wächst extrem schnell. - Lesen (KickBannerStats): Wir nutzen eine flache, aggregierte Tabelle namens
#__kickbannerstats_daily.
Tabellenstruktur
Die Tabelle #__kickbannerstats_daily speichert eine Zeile pro Banner, Kunde und Tag.
CREATE TABLE IF NOT EXISTS `#__kickbannerstats_daily`
(
`date` DATE NOT NULL,
`banner_id` INT UNSIGNED NOT NULL,
`client_id` INT UNSIGNED NOT NULL,
`impressions` INT UNSIGNED NOT NULL DEFAULT 0,
`clicks` INT UNSIGNED NOT NULL DEFAULT 0,
`banner_name` VARCHAR(255) NOT NULL,
`client_name` VARCHAR(255) NOT NULL,
`updated_at` DATETIME NOT NULL,
PRIMARY KEY (`date`, `banner_id`, `client_id`),
KEY `idx_banner_date` (`banner_id`, `date`),
KEY `idx_client_date` (`client_id`, `date`)
) ENGINE = InnoDB ...;Vorteile dieses Schemas:
- Komprimierung: Aus 1.000.000 Tracking-Events an einem Tag werden vielleicht nur 50 Zeilen (je nach Anzahl der aktiven Banner).
- Indexierung: Der
PRIMARY KEYüber Datum und IDs ermöglicht extrem schnelle Range-Queries (z.B. "Letzte 30 Tage").
2. Der ETL-Prozess (Task Plugin)
Die Daten gelangen nicht in Echtzeit in die Statistik-Tabelle, sondern über einen Scheduled Task (Geplante Aufgabe). Das Plugin plg_task_kickbannerstats übernimmt diese Arbeit.
Routine A: create.stats (Täglich)
Dieser Task ist das Arbeitspferd und sollte einmal täglich laufen.
- Zeitraum: Er greift standardmäßig die letzten 3 Tage ab (
backfillDaysParameter).
- Warum 3 Tage? Um sicherzustellen, dass Klicks kurz vor Mitternacht oder Zeitzonen-Differenzen korrekt erfasst werden, selbst wenn der Task mal einen Tag ausfällt.
- Aggregation: Er gruppiert die Rohdaten aus
#__banner_tracksnachDATE(track_date),banner_idundcid. - Upsert: Die Daten werden mit
INSERT ... ON DUPLICATE KEY UPDATEin die Zieltabelle geschrieben. Das bedeutet:
- Existiert der Eintrag für diesen Tag/Banner schon? -> Update (Zahlen aktualisieren).
- Existiert er noch nicht? -> Insert (Neu anlegen).
Routine B: backfillStats (Historisch)
Dieser Task dient der initialen Befüllung oder Reparatur. Er ist für große Datenmengen optimiert.
- Chunking: Er verarbeitet den gewählten Zeitraum nicht am Stück, sondern in Blöcken (z.B. 30 Tage).
- Memory Management: Dies verhindert, dass PHP bei jahrelangen Historien in ein
Memory Limitläuft. - Idempotenz: Kann gefahrlos mehrfach ausgeführt werden, da er bestehende Werte einfach überschreibt.
3. Datenabruf (Read Path)
Sobald die Daten in #__kickbannerstats_daily liegen, werden sie von der Komponente konsumiert.
Im Backend (MVC)
- DashboardModel: Summiert die Werte für den Dashboard-Zeitraum (z.B. 30 Tage). Die CTR (Click-Through-Rate) wird dabei "on the fly" berechnet (
Klicks / Impressionen * 100). - StatisticsModel: Listet die Tageswerte auf und ermöglicht Filterung nach Kunde/Banner.
Über die API (Headless)
Der StatisticsController stellt die Daten als JSON bereit.
- Er nutzt
Joomla\CMS\MVC\Controller\ApiController. - Er unterstützt Filterung via
filter[begin],filter[end], etc. - Er gibt die Daten direkt aus der aggregierten Tabelle zurück, was Antwortzeiten im Millisekunden-Bereich ermöglicht, selbst bei jahrelanger Historie.
Zusammenfassung
Die Architektur opfert Echtzeit-Daten (Daten sind max. 24h alt) zugunsten von massiver Performance-Steigerung und Skalierbarkeit für Reporting-Zwecke.