HyperLogLog - це вірогідна структура даних . Він підраховує кількість різних елементів у списку. Але порівняно з прямим способом його виконання (маючи набір і додаючи елементи до набору), він робить це приблизно.
Перш ніж подивитися, як це робить алгоритм HyperLogLog, треба зрозуміти, для чого це потрібно. Проблема прямого шляху полягає в тому, що він витрачає O(distinct elements)
місце. Чому тут існує велика O позначення замість просто різних елементів? Це тому, що елементи можуть бути різного розміру. Один елемент може бути 1
іншим елементом "is this big string"
. Тож якщо у вас є величезний список (або величезний потік елементів), це займе багато пам’яті.
Імовірнісний підрахунок
Як можна отримати розумну оцінку кількості унікальних елементів? Припустимо, що у вас є рядок довжиною, m
який складається {0, 1}
з однаковою ймовірністю. Яка ймовірність того, що він розпочнеться з 0, з 2 нулями, з k нулями? Це є 1/2
, 1/4
і 1/2^k
. Це означає, що якщо ви стикалися з рядком із k
нулями, ви приблизно проглядали 2^k
елементи. Тож це хороший вихідний пункт. Маючи список елементів, розподілених рівномірно, 0
і 2^k - 1
ви можете порахувати максимальну кількість найбільшого префіксу нулів у двійковому поданні, і це дасть вам розумну оцінку.
Проблема полягає в тому, що припущення про рівномірне розподілення чисел від 0
t 2^k-1
надто важко досягти (дані, з якими ми стикалися, здебільшого не є числами, майже ніколи не розподіляються рівномірно, і можуть бути між будь-якими значеннями. Але, використовуючи хорошу функцію хешування, ви можете припустити, що вихідні біти будуть рівномірно розподілені, і більшість хеширующих функцій мають виходи між 0
і 2^k - 1
( SHA1 дає вам значення між 0
і 2^160
). Отже, що ми домоглися поки що, ми можемо оцінити кількість унікальних елементів з максимальною простотою k
бітів, зберігаючи лише одна кількість log(k)
бітів розміру . Мінусом є те, що ми маємо величезну дисперсію в нашій оцінці. Класна річ, яку ми майже створилиВірогідний підрахунок документа 1984 року (він трохи розумніший з оцінкою, але ми все ще близькі).
LogLog
Перш ніж рухатися далі, ми повинні зрозуміти, чому наша перша оцінка не така велика. Причина в тому, що одна випадкова поява високочастотного 0-префіксного елемента може зіпсувати все. Одним із способів її вдосконалення є використання багатьох хеш-функцій, підрахунок макс для кожної з хеш-функцій і врешті-решт їх середнє значення. Це відмінна ідея, яка поліпшить оцінку, але папір LogLog використовує дещо інший підхід (можливо, тому що хешування - це дорого коштує).
Вони використовували один хеш, але розділили його на дві частини. Одне називається відро (загальна кількість відра є 2^x
), а інше - в основному те саме, що і наш хеш. Мені було важко зрозуміти, що відбувається, тому я наведу приклад. Припустимо , у вас є два елементи , і ваш хеш - функція , яка дає значення форми 0
для 2^10
виробництва 2 -х значень: 344
і 387
. Ви вирішили мати 16 відер. Отже, у вас є:
0101 011000 bucket 5 will store 1
0110 000011 bucket 6 will store 4
Маючи більше відра, ви зменшуєте дисперсію (ви використовуєте трохи більше місця, але вона все ще крихітна). За допомогою математичних навичок вони змогли кількісно оцінити помилку (яка є 1.3/sqrt(number of buckets)
).
HyperLogLog
HyperLogLog не вводить нових ідей, але в основному використовує багато математики для покращення попередньої оцінки. Дослідники встановили, що якщо ви вилучите з відра 30% найбільшої кількості, ви значно поліпшите оцінку. Вони також використовували інший алгоритм для усереднення чисел. Папір математично важкий.
І я хочу закінчити останнім документом, де показана вдосконалена версія алгоритму hyperLogLog (до цього часу я не встиг його повністю зрозуміти, але, можливо, пізніше я вдосконалю цю відповідь).