ClickHouse场景及其原理

ClickHouse场景及其原理
ClickHouse是Yandex公司于2016年开源的一个列式数据库管理系统。Yandex的核心产品是搜索引擎,非常依赖流量和在线广告业务,因此ClickHouse天生就适合用户流量分析。

这里直接从原始数据开始消费,通过Flink清洗任务将数据洗入数据仓库存储,在数据仓库经过作业清洗并在ClickHouse生成用户行为明细,可以称作无模型化明细数据。利用ClickHouse原生的RoaringBitMap函数对参与计算的行为人群交并差集计算。
那么难点和挑战在哪里?主要是 3 个方面:

  1. 人群包数据量多,基数大。平台的用户数上亿,仅抖音的 DAU 就好几亿,抖音、头条对应的人群包在亿级别。整体的人群基数大,对应的标签也非常多。
  2. 计算复杂(单次计算可能包含几百上千个人群包),从之前的图我们可以看出,广告主可以设定一个非常复杂的圈选条件。
  3. 查询时长要求短(小于 5 s),其实如果页面上等待时间超过 1s,是有明显感知。如果超过 5 s,那么广告主的体验确实会非常不好。
    ClickHouse有如下特点:
    ● 第一是快,特别适用于大宽表的场景,这个是其他引擎所不能比拟的。
    ● 第二是架构简单,我们可以很好地做很多定制化的开发,甚至去修改整个执行逻辑,这个我后面会提到,我们其实对于 ClickHouse 有比较大的改动。

标签、人群圈选
行为分析平台、标签画像平台、AB实验人群包都是基于ClickHouse的RBM(RoaringBitMap)实现,此外RBM还有其他多项应用,比如事件分析标签人群圈选、预计算的路径分析、创建用户行为的用户分群等。

标签建群

实现要点

  1. 根据标签ID的定义,从行为数据仓库中给每个人打标并生成相应的标签编码集,标签编码集通过Array[Array]的方式以uid作为主键写入到分布式ClickHouse标签表中。
    a. 如:标签1234定义为《用户在最近多少天浏览某个页面的次数》
    b. 用户uid=6666 标签编码集可能是
    [1234_03_page1_4, 1234_03_page2_4, 1234_03_page3_4, 1234_03_page4_4]
    表示用户1234最近3天浏览page1是4次,用户1234最近3天浏览page2是4次,用户1234最近3天浏览page3是4次,用户1234最近3天浏览page4是4次,
  2. 前端通过选择标签并选择其对应的维度,然后进行标签之间的交并差逻辑,并生成对应的规则RuleContent。
  3. 后端解析到RuleContent,并通过规则引擎(DFS生成bitmap语句)从元数据表中获取标签元数据(如维度的index和array index的对应关系/标签所在ck分布式表schame和表名等)生成对应的bitmap Sql语句,不同标签之间使用clickhouse之bitmap的交并差获取相应的目标人群。

采用性能最好的稀疏位图索引 RoaringBitmap 来表示一个标签对应的人群包。在这样的情况下,集合的计算可以转换到对应位图的计算例如 A 交上 B 和 C 的并集可以转换为RoaringBitmap的计算。

RoaringBitmap用来存储稀疏的数据
https://www.ics.uci.edu/~goodrich/teach/cs165/notes/BinPacking.pdf
采用分桶的思想来将稀疏数据存储节约内存。

● RoaringBitmap64是由一系列RoaringBitmap32表示。实现方式有很多种,一种比较通用的做法用map存储,是把前 32 位存成 key,value是后32 所对应的 RoaringBitmap32,RoaringBitmap32 的实现如图中所示。第一层称之为 Chunk(高 16 位),如果该取值范围内没有数据就不会创建 Chunk。第二层称之为Container(低 16 位),会依据数据分布进行创建。
● RoaringBitmap32使用两种容器结构:Array Container和Bitmap Container。Array Container存放稀疏的数据,Bitmap Container存放稠密的数据。若一个Container 里面的元素数量小于4096,就使用Array Container;反之就用Bitmap来存储值。
uid是否需要映射递增?
uid通过特定的编码方式(高32位表示某种含义,低32位表示某种含义),并非连续递增生成,这样会加大uid的稀疏性。当数据比较稀疏的时候,一个人群包对应的RoaringBitmap64由很多个 RoaringBitmap32组成,每个RoaringBitmap32内部又由很多个array container组成。而对有序数组的交并补计算尽管也比较高效,但是相比于bitmap计算来说还是有明显的差异。这样导致计算性能提升不上去。因此能不能通过编码的方式,对区间内的数据进行编码,让数据更加集中,从而提升计算效率。

希望达到如下效果:
● 编码后同一个区间内的用户相对集中
● 不同区间的用户编码后同样在不同的区间内
● 编码后同一个人群包同一个区间内的用户 id 相对集中
● 通过编码,能够非常好地加速计算,计算速度提升 1~2 个量级
● 编码的过程是在引擎内部实现的,对用户是无感知的。当数据导入的时候,会自动完成编码。
有这几个问题需要解决:

  1. 编码相当于是一个额外的工作量,会对导入有一定影响。同时,如果要导出 uid,需要增加额外的解码过程。如何减少编、解码带来的额外的代价。
  2. 原来为了能够尽快导入数据,我们是采用并行导入的方式。增加了额外的编码环节是否会导致导入必须要串行来完成,并行导入如果都在写字典是否会导致数据产生冲突
  3. 主备之间如何高效同步字典,避免字典的同步不及时导致数据无法解码。有一些一致性的问题要处理。
  4. 字典如何高效管理、备份,避免丢失。

组合建群

人群预估

人群画像
主要是对广告投放的用户群进行画像分析,也是在线的,同样对时间有一定的要求,因为是偏分析的场景,一般不能超过 20 秒,否则用户的体验就非常差了。
人群导入
基于ClickHouse构建的一套海量UBA技术解决方案,底层ClickHouse集群的稳定性 、读写性能、资源使用率均会影响上层业务的使用体验。与此同时,海量数据如何导入ClickHouse,以及数据导入过程的稳定性、导入效率、资源消耗在很大程度上决定了ClickHouse集群的整体稳定性和使用效率。所以,一个稳定高效的数据导入方案对于一套UBA解决方案来说是必不可少的。

统计分析
的使用场景比较多,在线、离线都有,包括一些搜索词统计分析,广告、投放收入数据的分析等等,应用的方面很多。

ClickHouse应用优化实践

在支持UBA场景各项功能模块的过程中,我们针对ClickHouse的查询,存储等方面做了大量应用优化工作。下面选取其中几个优化点做简单介绍。

查询下推
ClickHouse中的针对分布式表的查询会被改写成对local表的查询并发送到集群各个shard执行,然后将各个shard的中间计算结果收集到查询节点做合并。当中间计算结果很大时,比如countDistinct、 windowFunnel函数等,查询节点的数据收集和数据合并可能成为整个查询的性能瓶颈。
查询下推的思路就是尽量将计算都下推到各个shard执行,查询节点仅收集合并少量的最终计算结果。不过,也不是所有查询都适合做下推优化,满足以下两个条件的查询可以考虑做下推优化:
● 数据已经按照计算需求做好sharding:比如,UBA场景的数据已按user id做好了sharding,所以针对用户的漏斗分析,UV等计算可以下推到各个shard执行。否则,下推后的计算结果是不准确的。
● 计算的中间结果较大:sum,count等计算是无需下推的,因为其中间结果很小,合并计算很简单,下推并不能带来性能提升。

下面,我们以上文中提到的漏斗分析为例,阐述一下如何做查询下推。

上图是用windowFunnel函数实现漏斗分析的一个SQL,如图中“执行步骤”所示,该查询需要从各shard收集大量数据并在查询节点完成计算,会产生大量数据传输和单点计算量。
我们先使用配置distributed_group_by_no_merge做了一版下推优化:

优化SQL-V1将windowFunnel的计算下推到各个shard执行,仅在查询节点对windowFunnel的最终结果做聚合计算。在我们的场景下,该版本较上一版本性能提升了5倍以上。
为了更进一步做查询下推,我们利用cluster + view的函数组合,将聚合查询进一步下推:

优化SQL-V2的性能较优化SQL-V1进一步提升30+%.

Array和Map的跳数索引支持

UBA场景中的事件数据有很多公共属性和私有属性,公共属性被设计为表的固定字段,而私有属性因为各个事件不尽相同,所以采用Array/Map来存储。最初的设计是采用两个数组分别存储属性名和属性值,ClickHouse支持Map结构后,则在后续模块中采用Map来满足类似需求。无论是Array还是Map,最初都不支持创建跳数索引,所以在其他索引字段过滤效果有限的情况下,针对Array和Map的操作可能会成为查询的性能瓶颈。
针对这个问题,我们给Array和Map加上了Bloom filter等跳数索引支持,针对Map仅对其key构建索引。在某些出现频率较低的私有属性过滤场景下,Array/Map的跳数索引可以收获数倍的性能提升。

压缩算法优化
ClickHouse常用的数据压缩方式有三种,分别为LZ4、LZ4HC以及ZSTD。针对不同的数据类型,数据分布方式来使用特定的编码方式可以大大提高数据压缩率,以减少存储成本。
针对UBA场景,我们测试了不同压缩算法的压缩率,写入性能,查询性能。相较默认的LZ4,ZSTD(1)在压缩率上普遍可以节省30%以上的存储空间,查询性能方面未见明显差异,不过写入性能在某些场景下有20%左右的下降。由于UBA场景数据存储压力较大,同时对数据时效性要求不是很高,因此我们最终选择了ZSTD(1)作为主要的压缩方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/74763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端list.push,封装多个对象

js var fruit [apple, banana];fruit.push(pear);console.log(fruit); // [apple, banana, pear]现在为对象 data1:{addUser: 1,editUser: 1,addTime: null,editTime: 1527410579000,userId: 3,systemNo: mc,userName: zengzhuo,userPassword: e10adc3949ba59abbe56e057f20f88…

【广州华锐互动】AR远程协助技术提供实时远程协作和指导

随着科技的不断发展,企业的运营管理模式也在不断地进行创新和升级。在这个过程中,AR(增强现实)技术的应用逐渐成为了企业运维管理的新兴趋势。AR远程协助平台作为一种结合了AR技术和远程协助理念的技术手段,为企业运维…

Netty-NIO

文章目录 一、NIO-Selector1.处理accept2.cancel3.处理read4.处理客户端断开5. 处理消息的边界6. 写入内容过多的问题7. 处理可写事件 二、多线程优化三、NIO概念剖析1. stream 和 channel2. IO模型2.1 阻塞IO2.2 非阻塞IO2.3多路复用2.4 同步异步 3. 零拷贝3.1 NIO优化3.2 sen…

LeetCode 面试题 04.01. 节点间通路

文章目录 一、题目二、C# 题解 一、题目 节点间通路。给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。 点击此处跳转题目。 示例1: 输入: n 3, graph [[0, 1], [0, 2], [1, 2], [1, 2]], start 0, target 2 输出&#xff1…

点云从入门到精通技术详解100篇-三维点云帧间编码

目录 前言 国内外研究现状 几何信息编码研究现状 属性信息研究编码现状

hive葵花宝典:hive函数大全

文章目录 版权声明函数1 函数分类2 查看函数列表3 数学函数取整函数: round指定精度取整函数: round向下取整函数: floor向上取整函数: ceil取随机数函数: rand幂运算函数: pow绝对值函数: abs 4 字符串函数字符串长度函数:length字符串反转函数:reverse…

autoware.ai感知随笔--地面滤波

autwoware.ai中点云预处理–points_preprocessor points_preprocessor cloud_transformer: 点云坐标转换,将输入的点云转化为velodyne坐标系下的点云。 compare_map_filter: 对比激光雷达点云和点云地图,然后提取(或去除)一致的点。 |input_…

机器学习实战-系列教程7:SVM分类实战2线性SVM(鸢尾花数据集/软间隔/线性SVM/非线性SVM/scikit-learn框架)项目实战、代码解读

🌈🌈🌈机器学习 实战系列 总目录 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 SVM分类实战1之简单SVM分类 SVM分类实战2线性SVM SVM分类实战3非线性SVM 3、不同软间隔C值 3.1 数据标准化的影响 如图左边是没…

css 左右宽固定,中间自适应——双飞翼布局

最近面试的时候遇到一个提问说,如何做到一个左右宽度固定,中间自适应的布局,我的答案不重要,重要的是不是面试官想听到的答案,这样问大概率他想听到的答案一定是双飞翼布局,所以今天就手敲一个双飞翼布局让…

ES-索引管理

前言 数据类型 ​ 搜索引擎是对数据的检索,所以我们先从生活中的数据说起。我们生活中的数据总体分为两种: 结构化数据非结构化数据 结构化数据: 也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数…

智能合约编写高级篇(二)区块哈希介绍

本文档从区块哈希基本概念出发,详细介绍了中移链的区块哈希交易接口和应用方向。适用于EOS区块链智能合约高级开发人员,熟悉如何获取当前发生交易所在的区块号和区块哈希前缀,并通过Tapos机制验证交易的有效性。 01 概述 (一&…

【大模型】更强的开源可商用的中英文大语言模型baichuan2来了,从零开始搭建

【大模型】更强的开源可商用的中英文大语言模型baichuan2来了,从零开始搭建 Baichuan 2 介绍技术报告github 地址 模型下载开放协议协议 测试评估通用领域测试7B 模型结果13B 模型结果 法律、医疗7B 模型结果13B 模型结果 数学、代码7B 模型结果13B 模型结果 多语言…

html 学习 之 文本标签

下面是一些常见的HTML文本标签&#xff08;&#xff0c;&#xff0c;&#xff0c;&#xff0c;和&#xff09;以及它们的作用&#xff1a; 标签 (Emphasis - 强调): 作用&#xff1a;用于在文本中表示强调或重要性。 示例&#xff1a; <p>这是一段文本&#xff0c;&l…

数据资产管理:数据目录怎么搞?

经过了站在业务视角的自上而下的数据梳理&#xff0c;以及站在IT视角的自下而上的数据盘点&#xff0c;一套“热腾腾”的数据资产清单终于新鲜出炉了。 通过数据资产盘点&#xff0c;企业终于知道他们拥有哪些数据、如何使用数据、是否安全以及数据在哪里。 然而&#xff0c;据…

微博一面:JVM预热,你的方案是啥?

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如微博、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;遇到一几个很重要的面试题&#xff1a; JVM预热&#xff0c;你的方案是啥&#xff1f;Springb…

docker 和 podman的区别

Podman 和 Docker 都是用于容器化应用程序的工具&#xff0c;它们在很多方面非常相似&#xff0c;但也有一些关键区别&#xff1a; 1. 架构和权限&#xff1a; - Docker&#xff1a;Docker 使用守护进程&#xff08;dockerd&#xff09;来管理容器&#xff0c;它需要在操作…

TortoiseGit设置作者信息和用户名、密码存储

前言 Git 客户端每次与服务器交互&#xff0c;都需要输入密码&#xff0c;但是我们可以配置保存密码&#xff0c;只需要输入一次&#xff0c;就不再需要输入密码。 操作说明 在任意文件夹下&#xff0c;空白处&#xff0c;鼠标右键点击 在弹出菜单中按照下图点击 依次点击下…

侧边栏的文章分类、热门文章和热门文章的展示(Go 搭建 qiucode.cn 之九)

早就有言,秋码记录 虽早已不是原来的面貌,但这终究是不防碍我们使用golang来搭建它。 而又为什么是使用golang呢?并非是其他编程语言呢?想必 时候回答【我为什么要学习 Go 语言(golang)】这个问题了 已经给出了答案! 当然,当初学习golang时,不单单是为了搭建一个博客应…

【数据结构】二叉树基础入门

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

makefile之目标文件生成

目标文件:源码经过编译还没有链接那些中间文件.linux .o文件 gcc $(CFLAGS) -c xxx.c -o xx.o include Makefile.config SRC : $(wildcard *.c wildcard ./audio_module/*.c) SRC_OBJ $(patsubst %.c,%.o,$(SRC))all:$(SRC_OBJ) $(info contents $(SRC))$(info objfiles $(SR…