Building Video Heatmaps With HyperLogLog In PostgresQ

ਤੁਸੀਂ ਐਡੀਟਰਾਂ ਨੂੰ ਬਿਲਕੁਲ ਸਹੀ ਤਰੀਕੇ ਨਾਲ ਦਿਖਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ ਕਿ ਦੇਖਣ ਵਾਲੇ ਵੀਡੀਓ ਦੇ ਕਿਹੜੇ ਹਿੱਸੇ 'ਤੇ ਦੇਖਣਾ ਬੰਦ ਕਰ ਦਿੰਦੇ ਹਨ।

ਇਸ ਲਈ, ਤੁਹਾਨੂੰ ਇੱਕ ਹੀਟਮੈਪ (heatmap) ਦੀ ਲੋੜ ਹੈ। ਇਹ ਹੀਟਮੈਪ ਵੀਡੀਓ ਦੇ ਹਰ ਸੈਕਿੰਡ ਲਈ ਵਿਲੱਖਣ (unique) ਦੇਖਣ ਵਾਲਿਆਂ ਦੀ ਗਿਣਤੀ ਦਿਖਾਉਂਦਾ ਹੈ।

TrendVidStream ਵਿਖੇ, ਅਸੀਂ ਹਰ ਰੋਜ਼ 40 ਮਿਲੀਅਨ ਈਵੈਂਟਸ (events) ਨੂੰ ਪ੍ਰੋਸੈਸ ਕਰਦੇ ਹਾਂ। ਅਸੀਂ ਇੱਕ ਸਧਾਰਨ ਸਟੈਕ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹਾਂ: PHP 8.4 ਅਤੇ Postgres।

ਸਮੱਸਿਆ ਕਾਰਡੀਨੈਲਿਟੀ (cardinality) ਦੀ ਹੈ। ਹਰ ਸੈਕਿੰਡ ਲਈ ਵਿਲੱਖਣ ਦੇਖਣ ਵਾਲਿਆਂ ਦੀ ਗਿਣਤੀ ਕਰਨਾ ਮੁਸ਼ਕਲ ਹੈ।

ਸਧਾਰਨ ਤਰੀਕਾ:

  • ਇੱਕ ਰੋ (raw) ਈਵੈਂਟਸ ਟੇਬਲ ਦੀ ਵਰਤੋਂ ਕਰੋ।
  • COUNT(DISTINCT viewer_hash) ਚਲਾਓ।
  • ਵੀਡੀਓ ਅਤੇ ਟਾਈਮ ਬੱਕਟ (time bucket) ਅਨੁਸਾਰ ਗਰੁੱਪ ਕਰੋ।

ਇਹ ਤਰੀਕਾ ਜਲਦੀ ਹੀ ਫੇਲ ਹੋ ਗਿਆ। 90 ਦਿਨਾਂ ਦੇ ਡੇਟਾ ਲਈ, ਤੁਹਾਨੂੰ 3.6 ਬਿਲੀਅਨ ਰੋਅਜ਼ (rows) ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। ਕੁਐਰੀਆਂ (queries) ਚੱਲਣ ਵਿੱਚ 9 ਸੈਕਿੰਡ ਲੱਗਦੇ ਸਨ। ਇਸ ਤੋਂ ਇਲਾਵਾ, ਵਿਲੱਖਣ ਗਿਣਤੀ (unique counts) ਨੂੰ ਰੋਲਅੱਪ (roll up) ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। ਤੁਸੀਂ "ਪ੍ਰਤੀ ਘੰਟਾ ਵਿਲੱਖਣ" ਨੂੰ ਜੋੜ ਕੇ "ਪ੍ਰਤੀ ਦਿਨ ਵਿਲੱਖਣ" ਦੀ ਗਿਣਤੀ ਨਹੀਂ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਕਿਉਂਕਿ ਉਹੀ ਵਿਅਕਤੀ ਦੋਵਾਂ ਵਿੱਚ ਦਿਖਾਈ ਦੇ ਸਕਦਾ ਹੈ।

ਹੱਲ: HyperLogLog (HLL)।

HLL ਡੇਟਾ ਸੈੱਟ ਦਾ ਇੱਕ ਛੋਟਾ "ਸਕੇਚ" (sketch) ਬਣਾਉਂਦਾ ਹੈ। ਇਹ ਬਹੁਤ ਛੋਟਾ ਹੁੰਦਾ ਹੈ, ਲਗਭਗ 10 KB, ਚਾਹੇ ਲੱਖਾਂ ਲੋਕ ਹੀ ਕਿਉਂ ਨਾ ਦੇਖ ਰਹੇ ਹੋਣ।

HLL ਹੀਟਮੈਪ ਲਈ ਕਿਉਂ ਕੰਮ ਕਰਦਾ ਹੈ:

  • ਨਿਸ਼ਚਿਤ ਆਕਾਰ: ਇਹ ਛੋਟਾ ਹੀ ਰਹਿੰਦਾ ਹੈ।
  • ਮਰਜ ਕਰਨ ਯੋਗ (Mergeable): ਤੁਸੀਂ ਗਲੋਬਲ ਕਾਊਂਟ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ ਦੋ ਸਕੇਚਾਂ ਨੂੰ ਯੂਨੀਅਨ (union) ਕਰ ਸਕਦੇ ਹੋ। ਇਹ ਰੋਲਅੱਪ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਹੱਲ ਕਰਦਾ ਹੈ।

ਸਾਡੀ ਇੰਪਲੀਮੈਂਟੇਸ਼ਨ (Implementation):

ਅਸੀਂ postgresql-hll ਐਕਸਟੈਂਸ਼ਨ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹਾਂ। ਅਸੀਂ ਦੋ ਟੇਬਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹਾਂ।

  1. ਇੱਕ ਸਟੇਜਿੰਗ ਟੇਬਲ (staging table): ਇੱਕ ਅਪੈਂਡ-ਓਨਲੀ (append-only) ਟੇਬਲ ਜਿੱਥੇ PHP ਰੋ ਹਾਰਟਬੀਟਸ (raw heartbeats) ਲਿਖਦਾ ਹੈ। ਲਿਖਣ ਦੀ ਪ੍ਰਕਿਰਿਆ ਨੂੰ ਤੇਜ਼ ਰੱਖਣ ਲਈ ਅਸੀਂ ਇੱਥੇ ਇੰਡੈਕਸਾਂ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰਦੇ।
  2. ਇੱਕ ਸਕੇਚ ਟੇਬਲ (sketch table): ਇਹ 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' ਪੈਦਾ ਕਰ ਦਿਓਗੇ।
  • ਹੈਸ਼ਾਂ ਲਈ ਰੋਜ਼ਾਨਾ ਸਾਲਟ (salt) ਦੀ ਵਰਤੋਂ ਕਰੋ। ਇਹ ਪ੍ਰਾਈਵੇਸੀ ਦੀ ਰੱਖਿਆ ਕਰਦਾ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਰੋਜ਼ਾਨਾ ਦੇ ਸਕੇਚਾਂ ਨੂੰ ਸਾਫ਼ ਰੱਖਦਾ ਹੈ।

ਜੇਕਰ ਤੁਹਾਡਾ ਡੈਸ਼ਬੋਰਡ COUNT(DISTINCT) ਕਾਰਨ ਹੌਲੀ ਚੱਲ ਰਿਹਾ ਹੈ, ਤਾਂ ਤੁਹਾਨੂੰ ਕਿਸੇ ਵਿਸ਼ਾਲ ਡੇਟਾ ਵੇਅਰਹਾਊਸ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ। ਤੁਹਾਨੂੰ HLL ਦੀ ਲੋੜ ਹੈ।

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