
# HyperLogLog函数
HetuEngine使用HyperLogLog数据结构实现rox_distinct()函数。
#### 数据结构
HyperLogLog（hll）是一种统计基数的算法。它实际上不会存储每个元素出现的次数，它使用的是概率算法，通过存储元素的32位hash值的第一个1的位置，来计算元素数量。通常分为稀疏存储结构和密集存储结构两种。hll创建时是稀疏存储结构，当需要更高效处理时会转为密集型数据结构。P4HyperLogLog则在其整个生命周期都是密集型数据结构。如有必要，可以显式地转换cast(hll as P4HyperLogLog)。在当前数据引擎的实现中，hll的数据草图是通过一组32位的桶来存储对应的最大hash。
#### 序列化
数据草图可以通过varbinary进行序列化和反序列化。这使得可以被方便地存储，以备后用。通过合并多个草图，可以在查询分区中所有元素的approx_distinct()，即每个元素出现的近似次数，进而通过很小的开销去完成整个查询。
例如，只要计算每日每个用户浏览了多少次网页，就可以通过累加的方式，去计算每周、每年对应的数据，类似于通过汇总每日收入来计算每周收入。
可以将approx_distinct()与GROUPING SETS一起使用转换为HyperLogLog。如下所示：
```
CREATE TABLE visit_summaries(visit_date date,hll varbinary);
INSERT INTO visit_summaries 
SELECT visit_date,cast(approx_set(user_id) AS varbinary) 
FROM user_visits 
GROUP BY visit_date; 
SELECT cardinality(merge(cast(hll AS HyperLogLog)))AS weekly_unique_users 
FROM visit_summaries
WHERE visit_date>=current_date-interval'7'day;
```
#### 函数
- approx_set(*x* ) → HyperLogLog
  描述：返回HyperLogLog。这个数据草图是approx distinct()的基础，可以通过调用cardinality()来存储和使用。
  ```
  select approx_set(cookieid) from cookies_log;--02 0c 02 00 c0 77 15 40 c1 2f 1b c2
  ```
  

- cardinality(*hll* ) → bigint
  描述：计算hll汇总的数据。
  ```
  select cardinality(approx_set(cookieid)) from cookies_log; --2
  ```
  
- empty_approx_set()→ HyperLogLog 描述：返回一个空的hyperloglog。
  ```
  select empty_approx_set();--02 0c 00 00
  ```
  
- merge(*HyperLogLog* ) → HyperLogLog
  描述：对每个独立的hll数据草图进行汇总求并集的操作。
  ```
  CREATE TABLE visit_summaries (  visit_date date,  hll varbinary);
  insert into visit_summaries select createtime,cast(approx_set(cookieid) as varbinary) from cookies_log group by createtime;
  SELECT cardinality(merge(cast(hll AS HyperLogLog))) AS weekly_unique_users FROM visit_summaries WHERE visit_date >=date '2020-07-11';
   weekly_unique_users 
  ---------------------
                     2 
  (1 row)
  ```
  
 
