iis网站数据库失败,青海西宁今天刚刚紧急通知,优质网站建设是哪家,百姓网官网首页ClickHouse场景及其原理 ClickHouse是Yandex公司于2016年开源的一个列式数据库管理系统。Yandex的核心产品是搜索引擎#xff0c;非常依赖流量和在线广告业务#xff0c;因此ClickHouse天生就适合用户流量分析。
这里直接从原始数据开始消费#xff0c;通过Flink清洗任务将…ClickHouse场景及其原理 ClickHouse是Yandex公司于2016年开源的一个列式数据库管理系统。Yandex的核心产品是搜索引擎非常依赖流量和在线广告业务因此ClickHouse天生就适合用户流量分析。
这里直接从原始数据开始消费通过Flink清洗任务将数据洗入数据仓库存储在数据仓库经过作业清洗并在ClickHouse生成用户行为明细可以称作无模型化明细数据。利用ClickHouse原生的RoaringBitMap函数对参与计算的行为人群交并差集计算。 那么难点和挑战在哪里主要是 3 个方面
人群包数据量多基数大。平台的用户数上亿仅抖音的 DAU 就好几亿抖音、头条对应的人群包在亿级别。整体的人群基数大对应的标签也非常多。计算复杂单次计算可能包含几百上千个人群包从之前的图我们可以看出广告主可以设定一个非常复杂的圈选条件。查询时长要求短小于 5 s其实如果页面上等待时间超过 1s是有明显感知。如果超过 5 s那么广告主的体验确实会非常不好。 ClickHouse有如下特点 ● 第一是快特别适用于大宽表的场景这个是其他引擎所不能比拟的。 ● 第二是架构简单我们可以很好地做很多定制化的开发甚至去修改整个执行逻辑这个我后面会提到我们其实对于 ClickHouse 有比较大的改动。
标签、人群圈选 行为分析平台、标签画像平台、AB实验人群包都是基于ClickHouse的RBM(RoaringBitMap)实现此外RBM还有其他多项应用比如事件分析标签人群圈选、预计算的路径分析、创建用户行为的用户分群等。
标签建群
实现要点
根据标签ID的定义从行为数据仓库中给每个人打标并生成相应的标签编码集标签编码集通过Array[Array]的方式以uid作为主键写入到分布式ClickHouse标签表中。 a. 如标签1234定义为《用户在最近多少天浏览某个页面的次数》 b. 用户uid6666 标签编码集可能是 [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次前端通过选择标签并选择其对应的维度然后进行标签之间的交并差逻辑并生成对应的规则RuleContent。后端解析到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 位存成 keyvalue是后32 所对应的 RoaringBitmap32RoaringBitmap32 的实现如图中所示。第一层称之为 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 个量级 ● 编码的过程是在引擎内部实现的对用户是无感知的。当数据导入的时候会自动完成编码。 有这几个问题需要解决
编码相当于是一个额外的工作量会对导入有一定影响。同时如果要导出 uid需要增加额外的解码过程。如何减少编、解码带来的额外的代价。原来为了能够尽快导入数据我们是采用并行导入的方式。增加了额外的编码环节是否会导致导入必须要串行来完成并行导入如果都在写字典是否会导致数据产生冲突主备之间如何高效同步字典避免字典的同步不及时导致数据无法解码。有一些一致性的问题要处理。字典如何高效管理、备份避免丢失。
组合建群
人群预估
人群画像 主要是对广告投放的用户群进行画像分析也是在线的同样对时间有一定的要求因为是偏分析的场景一般不能超过 20 秒否则用户的体验就非常差了。 人群导入 基于ClickHouse构建的一套海量UBA技术解决方案底层ClickHouse集群的稳定性 、读写性能、资源使用率均会影响上层业务的使用体验。与此同时海量数据如何导入ClickHouse以及数据导入过程的稳定性、导入效率、资源消耗在很大程度上决定了ClickHouse集群的整体稳定性和使用效率。所以一个稳定高效的数据导入方案对于一套UBA解决方案来说是必不可少的。
统计分析 的使用场景比较多在线、离线都有包括一些搜索词统计分析广告、投放收入数据的分析等等应用的方面很多。
ClickHouse应用优化实践
在支持UBA场景各项功能模块的过程中我们针对ClickHouse的查询存储等方面做了大量应用优化工作。下面选取其中几个优化点做简单介绍。
查询下推 ClickHouse中的针对分布式表的查询会被改写成对local表的查询并发送到集群各个shard执行然后将各个shard的中间计算结果收集到查询节点做合并。当中间计算结果很大时比如countDistinct、 windowFunnel函数等查询节点的数据收集和数据合并可能成为整个查询的性能瓶颈。 查询下推的思路就是尽量将计算都下推到各个shard执行查询节点仅收集合并少量的最终计算结果。不过也不是所有查询都适合做下推优化满足以下两个条件的查询可以考虑做下推优化 ● 数据已经按照计算需求做好sharding比如UBA场景的数据已按user id做好了sharding所以针对用户的漏斗分析UV等计算可以下推到各个shard执行。否则下推后的计算结果是不准确的。 ● 计算的中间结果较大sumcount等计算是无需下推的因为其中间结果很小合并计算很简单下推并不能带来性能提升。
下面我们以上文中提到的漏斗分析为例阐述一下如何做查询下推。
上图是用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场景我们测试了不同压缩算法的压缩率写入性能查询性能。相较默认的LZ4ZSTD(1)在压缩率上普遍可以节省30%以上的存储空间查询性能方面未见明显差异不过写入性能在某些场景下有20%左右的下降。由于UBA场景数据存储压力较大同时对数据时效性要求不是很高因此我们最终选择了ZSTD(1)作为主要的压缩方式。