Apache Kylin中对上亿字符串的精确Count_Distinct示例
如果业务中能接受1.22%的误差,那么肯定首选近似算法,因为它能节省很多资源和时间。如果业务中必须使用精确去重,那么就看看本文的例子(针对上亿字符串的精确去重)。
事实表
- hive> desc test_t_pbs_uv_fact;
- OK
- ad_id string //维度
- material_id string //维度
- city_code string //维度
- user_id string //指标,需要精确Count Distinct
- bid_request bigint //指标,SUM
- device_bid_request bigint //指标,SUM
- win bigint //指标,SUM
- ck bigint //指标,SUM
- pt string //维度,日期,yyyy-MM-dd
该事实表一天的数据记录大概1.5亿+,其中user_id为字符串,类似MD5后的字符串。
创建Model
在Kylin中创建名为lxw1234_uv_model的模型。
选择维度和指标字段:
创建Cube
创建名为lxw1234_uv_cube的Cube,其中,指标定义如下:
其他请按实际业务需求配置。
手动修改Cube(JSON)
如果不修改,精确Count Distinct使用了Default dictionary来保存编码后的user_id,而Default dictionary的最大容量为500万,并且,会为每个Segment生成一个Default dictionary,这样的话,跨天进行UV分析的时候,便会产生错误的结果,如果每天不重复的user_id超过500万,那么build的时候会报错:
- java.lang.IllegalArgumentException: Too high cardinality is not suitable for dictionary — cardinality: 43377845
- at org.apache.kylin.dict.DictionaryGenerator.buildDictionary(DictionaryGenerator.java:96)
- at org.apache.kylin.dict.DictionaryGenerator.buildDictionary(DictionaryGenerator.java:73)
该值由参数 kylin.dictionary.max.cardinality 来控制,当然,你可以修改该值为1亿,但是Build时候可能会因为内存溢出而导致Kylin Server挂掉:
- # java.lang.OutOfMemoryError: Requested array size exceeds VM limit
- # -XX:OnOutOfMemoryError=”kill -9 %p”
- # Executing /bin/sh -c “kill -9 16193″…
因此,这种需求我们需要手动使用Global Dictionary,顾名思义,它是一个全局的字典,不分Segments,同一个user_id,在全局字典中只有一个ID。
目前Kylin的UI中没有可以直接配置Global Dictionary的地方,需要手动修改Cube的JSON描述:
在状态为DISABLED的Cube列表中,点击”Admins”菜单下的”Edit(JSON)”,进入Cube JSON描述的编辑页面,
添加下面的JSON
其中,在override_kylin_properties 中增加了两个Cube的配置参数,用于增加Mapper的运行内存。
- "dictionaries": [
- {
- "column": "USER_ID",
- "builder": "org.apache.kylin.dict.GlobalDictionaryBuilder"
- }
- ]
定义了对USER_ID字段使用全局字典。
之后,保存JSON。
Build与查询
Build完成后,在Hive和Kylin中执行下面的查询:
SELECT city_code,SUM(bid_request) AS bid_request,COUNT(DISTINCT user_id) AS uvFROM liuxiaowen.TEST_T_PBS_UV_FACTGROUP BY city_codeORDER BY uv DESC limit 30;
Hive中耗时:181.134 seconds
Kylin中耗时:9 seconds
查询结果完全一致:
Global Dictionary存在问题
由于Global Dictionary 底层基于bitmap,其最大容量为Integer.MAX_VALUE,即21亿多,如果全局字典中,累计值超过Integer.MAX_VALUE,那么在Build时候便会报错。
因此,使用全局字典还是有容量的限制。
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的