בניית מפות חום (Heatmaps) לווידאו באמצעות HyperLogLog ב-Postgres

אתם רוצים להראות לעורכים בדיוק איפה הצופים מפסיקים לצפות בווידאו.

כדי לעשות זאת, אתם זקוקים למפת חום (heatmap). מפת חום זו מציגה צופים ייחודיים עבור כל שנייה בווידאו.

ב-TrendVidStream, אנחנו מעבדים 40 מיליון אירועים בכל יום. אנחנו משתמשים בסטאק פשוט: PHP 8.4 ו-Postgres.

הבעיה היא ה-cardinality. ספירת צופים ייחודיים לכל שנייה היא משימה קשה.

הדרך הנאיבית:

  • שימוש בטבלת אירועים גולמית (raw events table).
  • הרצת COUNT(DISTINCT viewer_hash).
  • קיבוץ (Group by) לפי וידאו וחלון זמן (time bucket).

השיטה הזו נכשלה במהירות. עבור 90 ימי נתונים, אתם זקוקים ל-3.6 מיליארד שורות. השאילתות ארכו 9 שניות. בנוסף, ספירות ייחודיות לא ניתנות לסיכום (roll up). אי אפשר לסכום "ייחודיים לשעה" כדי לקבל "ייחודיים ליום" מכיוון שאותו אדם מופיע בשניהם.

הפתרון: HyperLogLog (HLL).

HLL יוצר "sketch" (סקיצה) קטן של סט הנתונים. הוא זעיר, בסביבות 10 KB, ללא קשר לכמות המיליונים שצופים בווידאו.

למה HLL עובד עבור מפות חום:

  • גודל קבוע: הוא נשאר קטן.
  • ניתן למיזוג (Mergeable): ניתן לבצע union לשתי סקיצות כדי לקבל ספירה גלובלית. זה פותר את בעיית ה-rollup.

המימוש שלנו:

אנחנו משתמשים בתוסף postgresql-hll. אנחנו משתמשים בשתי טבלאות.

  1. טבלת staging: טבלה מסוג append-only שבה PHP כותב heartbeats גולמיים. אנחנו לא משתמשים באינדקסים כאן כדי לשמור על כתיבה מהירה.
  2. טבלת sketch: זו שומרת את נתוני ה-HLL.

אנחנו משתמשים ב-cron job כדי להעביר נתונים מטבלת ה-staging לטבלת ה-sketch. אנחנו משתמשים בפקודה הזו:

INSERT INTO video_heatmap (...) SELECT ..., hll_add_agg(hll_hash_text(viewer_hash), 14, 5) FROM beacon_staging GROUP BY ... ON CONFLICT (...) DO UPDATE SET viewers = video_heatmap.viewers || EXCLUDED.viewers;

האופרטור "||" ממזג את הנתונים החדשים לתוך ה-sketch הקיים.

התוצאות:

  • מהירות שאילתות: שאילתות מפת החום שלנו אורכות בין 15 ל-40 מילי-שניות (ms). הדרך הישנה ארכה 9 שניות.
  • אחסון: סט הנתונים שלנו ל-90 יום הוא 40 GB. הדרך הישנה הייתה דורשת 1.2 TB.
  • דיוק: אנחנו רואים שגיאה של כ-0.6% עד 1.4%. עבור מפת חום, זה מושלם.

לקחים שנלמדו:

  • בצעו hashing בתוך מסד הנתונים. אל תבצעו hashing באפליקציה שלכם.
  • בצעו עדכונים ב-batch. אל תעדכנו sketches שורה אחר שורה, אחרת תיצרו write hotspots.
  • השתמשו ב-salt יומי עבור ה-hashes. זה מגן על הפרטיות ושומר על ה-sketches היומיים שלכם נקיים.

אם ה-dashboard שלכם איטי בגלל COUNT(DISTINCT), אתם לא זקוקים למחסן נתונים (data warehouse) עצום. אתם זקוקים ל-HLL.

מקור: https://dev.to/ahmet_gedik778845/building-per-second-video-heatmap-analytics-with-hyperloglog-in-postgres-2p22