Postgres में HyperLogLog के साथ वीडियो हीटमैप बनाना

आप एडिटर्स को ठीक वही जगह दिखाना चाहते हैं जहाँ दर्शक वीडियो देखना बंद कर देते हैं।

इसके लिए, आपको एक हीटमैप की आवश्यकता है। यह हीटमैप वीडियो के हर सेकंड के लिए यूनिक (unique) दर्शकों को दिखाता है।

TrendVidStream में, हम हर दिन 40 मिलियन इवेंट्स प्रोसेस करते हैं। हम एक सरल स्टैक का उपयोग करते हैं: PHP 8.4 और Postgres।

समस्या कार्डिनैलिटी (cardinality) की है। प्रति सेकंड यूनिक दर्शकों को गिनना कठिन है।

साधारण तरीका:

  • एक रॉ इवेंट्स टेबल का उपयोग करें।
  • COUNT(DISTINCT viewer_hash) चलाएं।
  • वीडियो और टाइम बकेट के आधार पर ग्रुप करें।

यह तरीका जल्दी ही विफल हो गया। 90 दिनों के डेटा के लिए, आपको 3.6 बिलियन पंक्तियों (rows) की आवश्यकता होती है। क्वेरीज़ में 9 सेकंड लग रहे थे। साथ ही, यूनिक काउंट्स को रोल अप (roll up) नहीं किया जा सकता। आप "प्रति घंटा यूनिक" को जोड़कर "प्रति दिन यूनिक" प्राप्त नहीं कर सकते क्योंकि वही व्यक्ति दोनों में दिखाई देता है।

समाधान: HyperLogLog (HLL)।

HLL डेटासेट का एक छोटा "स्केच" (sketch) बनाता है। यह बहुत छोटा होता है, लगभग 10 KB, चाहे कितने भी मिलियन लोग इसे देखें।

हीटमैप के लिए HLL क्यों काम करता है:

  • फिक्स्ड साइज: यह छोटा बना रहता है।
  • मर्ज करने योग्य (Mergeable): आप ग्लोबल काउंट प्राप्त करने के लिए दो स्केच को यूनियन कर सकते हैं। यह रोलअप की समस्या को हल करता है।

हमारा कार्यान्वयन (Implementation):

हम postgresql-hll एक्सटेंशन का उपयोग करते हैं। हम दो टेबल का उपयोग करते हैं।

  1. एक स्टेजिंग टेबल: एक अपेंड-ओनली (append-only) टेबल जहाँ PHP रॉ हार्टबीट्स लिखता है। हम राइट्स (writes) को तेज़ रखने के लिए यहाँ इंडेक्स का उपयोग नहीं करते हैं।
  2. एक स्केच टेबल: यह HLL डेटा को स्टोर करती है।

हम स्टेजिंग से स्केच टेबल में डेटा ले जाने के लिए क्रॉन जॉब (cron job) का उपयोग करते हैं। हम इस कमांड का उपयोग करते हैं:

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;

"||" ऑपरेटर नए डेटा को मौजूदा स्केच में मर्ज कर देता है।

परिणाम:

  • क्वेरी स्पीड: हमारी हीटमैप क्वेरीज़ में 15 से 40 ms लगते हैं। पुराने तरीके में 9 सेकंड लगते थे।
  • स्टोरेज: हमारा 90-दिन का डेटासेट 40 GB है। पुराने तरीके में यह 1.2 TB लेता।
  • सटीकता: हमें लगभग 0.6% से 1.4% की त्रुटि (error) दिखती है। एक हीटमैप के लिए, यह एकदम सही है।

सीखे गए सबक:

  • डेटाबेस के अंदर हैश (hash) करें। अपने ऐप में हैश न करें।
  • अपने अपडेट्स को बैच (batch) में करें। स्केच को एक बार में एक पंक्ति करके अपडेट न करें, अन्यथा आप राइट हॉटस्पॉट्स (write hotspots) बना देंगे।
  • हैश के लिए डेली साल्ट (daily salt) का उपयोग करें। यह गोपनीयता की रक्षा करता है और आपके दैनिक स्केच को साफ रखता है।

यदि आपका डैशबोर्ड COUNT(DISTINCT) के कारण धीमा है, तो आपको किसी विशाल डेटा वेयरहाउस की आवश्यकता नहीं है। आपको HLL की आवश्यकता है।

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