【clickhouse】ClickHouse中的低基数(LowCardinality)类型
文章目录
- 1.概述
- 2.为什么要有LowCardinality
- 3.做个小实验
- 4.低基数的背后
1.概述
转载:https://www.jianshu.com/p/f361e7cfc8b3
2.为什么要有LowCardinality
在常见数据库系统的类型体系中,字符串是最灵活、表意性最强的类型,但是存储成本无疑也最高。ClickHouse提供了两种简单字符串的更优的存储方式,即:
- 存储固定长度(按字节数计)字符串的
FixedString
类型, - 以及将字符串转为定长整形枚举值的
Enum
类型。
但是,我们平时见到的字符串绝大多数都是变长的,只有哈希值、IP等少数种类适合用FixedString存储
;并且数据的定义域可能会经常变动,频繁修改Enum字段来增加枚举值也显然不可行
。因此,ClickHouse又提供了第三条路,即LowCardinality
——“低基数”类型。顾名思义,它适合长度和定义域都可变,但总体基数不是特别大的列。
根据官方文档,低基数是一种修饰类型,即用法为LowCardinality
(type)。其中type表示的原始类型可以是String、FixedString、Date、DateTime,以及除了Decimal之外的所有数值类型。但是,LowCardinality
的设计初衷就是为了优化字符串存储
,修饰其他类型的效率未必会更高,所以下面只考虑LowCardinality(String)的情况。
- LowCardinality(Type),是一种数据类型上的字典编码封装。LowCardinality(String),别名StringWithDictionary,是最常见的LowCardinality类型。
- 使用LowCardinality编码的字段,在底层数据存储上做了修改。
- 适用场景:适用于原始string字段冗长且去重后的计数值<1000w
- 优势:使用lowCardinality能优化存储、过滤、聚合以及部分的函数,例如length()。
3.做个小实验
来创建两张MergeTree测试表,其中一个用普通String类型,另一个用低基数String类型。
CREATE TABLE test.user_event_common_str (user_id Int64,event_type String
) ENGINE = MergeTree()
ORDER BY user_id;CREATE TABLE test.user_event_lowcard_str (user_id Int64,event_type LowCardinality(String)
) ENGINE = MergeTree()
ORDER BY user_id;
从我们的埋点日志表中取一些数据(总计约2.3亿行)分别存入两张表中。event_type字段表示埋点事件类型,目前约有100种,且会随着应用的迭代而增加。
做个简单的聚合查询:
:) SELECT event_type,count() AS cnt
FROM test.user_event_lowcard_str
GROUP BY event_type ORDER BY cnt DESC;
-- ...
105 rows in set. Elapsed: 0.050 sec. Processed 229.77 million rows, 240.39 MB (4.59 billion rows/s., 4.80 GB/s.):) SELECT event_type,count() AS cnt
FROM test.user_event_common_str
GROUP BY event_type ORDER BY cnt DESC;
-- ...
105 rows in set. Elapsed: 0.297 sec. Processed 229.77 million rows, 5.34 GB (774.40 million rows/s., 18.00 GB/s.)
可见在这个场景下,对低基数String进行聚合,速度是对普通String进行聚合的6倍,并且读取的数据量只有原来的4.5%。从系统表中查询存储空间的占用,低基数String也明显要更小:
:) SELECT table,column,sum(rows) AS rows,formatReadableSize(sum(column_data_compressed_bytes)) AS comp_bytes,formatReadableSize(sum(column_data_uncompressed_bytes)) AS uncomp_bytes
FROM system.parts_columns
WHERE table LIKE 'user_event_%_str' AND column = 'event_type'
GROUP BY table,column;┌─table──────────────────┬─column─────┬──────rows─┬─comp_bytes─┬─uncomp_bytes─┐
│ user_event_lowcard_str │ event_type │ 229770105 │ 186.89 MiB │ 219.57 MiB │
│ user_event_common_str │ event_type │ 229770105 │ 599.33 MiB │ 3.26 GiB │
└────────────────────────┴────────────┴───────────┴────────────┴──────────────┘
我们甚至可以用DDL语句将String类型的列直接修改为低基数String类型的列,速度也相当快:
:) ALTER TABLE test.user_event_common_str
MODIFY COLUMN event_type LowCardinality(String);0 rows in set. Elapsed: 7.420 sec.
4.低基数的背后
LowCardinality的实现方法同样简单而高效,即字典压缩编码(dictionary encoding)加上倒排索引(reverse index),如下图所示。事实上,LowCardinality(String)类型还有一个别名StringWithDictionary,更贴近其本质。
一旦有了字典,很多对字符串进行操作的函数就可以下推到字典上执行(如下图所示),效率很高。另外,同一个字典上的操作会被缓存(甚至包括GROUP BY子句产生的哈希值),不必每次都进行计算。
最后,ClickHouse还提供了low_cardinality_max_dictionary_size参数来控制单个字典的大小阈值,默认为8192。也就是说,如果LowCardinality(String)列的基数大于该阈值,就会被拆分成多个字典文件存储。
那么,低基数String的基数控制在什么范围内的效率最高呢
?关于这点,官方文档和Altinity的blog给出了完全不同的答案。前者认为控制在万级别以内较好,而后者认为10M(即约1000万)以下都可以。笔者利用现有数据集进行测试,String的基数是10万级别,采用LowCardinality的聚合效率仍然是普通String的4倍左右,看官可酌情参考。
【clickhouse】ClickHouse中的低基数(LowCardinality)类型相关推荐
- 聊聊ClickHouse中的低基数LowCardinality类型
原文链接????:https://www.jianshu.com/p/f361e7cfc8b3 2020年快要过去了,写博客的习惯还是得捡起来.最近刚刚忙完搬家的事情,抽出一点时间简单聊两句. 为什么 ...
- 一文讲懂图像处理中的低通、高通、带阻和带通滤波器
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 空间域和频域滤波器通常分为四种类型的滤波器--低通.高通.带阻和带 ...
- Nat. Mach. Intell. | 基于神经网络的迁移学习用于单细胞RNA-seq分析中的聚类和细胞类型分类...
今天给大家介绍由美国宾夕法尼亚大学佩雷尔曼医学院生物统计学,流行病学和信息学系Jian Hu等人在<Nature Machine Intelligence>上发表了一篇名为"It ...
- 可以获取python整数类型帮助的是什么-下列选项中可以获取Python整数类型帮助的是...
[单选题]关于 Python 语言的特点,以下选项中描述错误的是 [单选题]下面代码的输出结果是: s1 = "The python language is a scripting lang ...
- 详解音视频直播中的低延时
高泽华,声网 Agora 音频工匠,先后在中磊电子.士兰微电子.虹软科技主导音频项目.任职 YY 期间负责语音音频技术工作.在音乐.语音编解码方面有超过十年的研发经验. 音视频实时通讯的应用场景已经随 ...
- 【CV】一文讲懂图像处理中的低通、高通、带阻和带通滤波器
空间域和频域滤波器通常分为四种类型的滤波器--低通.高通.带阻和带通滤波器.在本文中,我们为每一种滤波器提供了注释.代码示例和图像输出. 滤波器类型 低通滤波器:只允许通过低频细节,衰减高频细节.例如 ...
- java是如何实现原语的_Java中的低GC:使用原语而不是包装器
java是如何实现原语的 总览 有两个很好的理由在可能的地方使用原语而不是包装器. 明晰. 通过使用原语,您可以清楚地知道null值是不合适的. 性能. 使用原语通常更快. 清晰度通常比性能更重要,并 ...
- Java中的低GC:使用原语而不是包装器
总览 有两个很好的理由在可能的地方使用原语而不是包装器. 明晰. 通过使用原语,您可以清楚地知道null值是不合适的. 性能. 使用原语通常更快. 清晰度通常比性能更重要,并且是使用它们的最佳理由. ...
- 在c语言中出现的int错误类型,【揭秘】C语言类型转换时发生了什么?
原标题:[揭秘]C语言类型转换时发生了什么? ID:技术让梦想更伟大 作者:李肖遥 在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统,我们常用的算术类型包括两种类型:整数类型和浮 ...
最新文章
- MECARD格式的电子名片简单介绍
- 今天收到IBM cat 测试
- 【Groovy】MOP 元对象协议与元编程 ( Groovy 类内部和外部分别获取 metaClass | 分析获取 metaClass 操作的字节码 | HandleMetaClass 注入方法 )
- 搞明白这八个问题,Linux系统就好学多了
- golang包管理解决之道——go modules初探
- python编程游戏手机版_利用Python开发手机同款游戏:开心消消乐
- [云炬创业基础笔记]第二章创业者测试8
- Struts 1高级应用
- kafka java客户端消息的分区与缓存发送
- “我爱淘”第二冲刺阶段Scrum站立会议4
- 目标检测(十八)--FPN
- 【论文撰写和程序员常用软件】
- 路由器与交换机的区别与联系
- python多元线性回归报错(assert pytype not in (tokenize.NL, tokenize.NEWLINE))
- 大数据的兴起,数据科学家的崛起
- linux卸载exe文件怎么恢复,linux中误删除程序包恢复实例
- 从零开始写项目第三篇【在线聊天和个人收藏夹】
- CAN IP SjA1000ip核 verilog写的 项目以在稳定的用
- 医院网络营销到底该怎么做
- 学c语言把电脑弄坏了,一不小心把学校的电脑弄坏了怎么样写检讨四百字
热门文章
- 百度2021年Q2净利润54亿元,智能云收入同比增71%
- 最便宜的骁龙888旗舰机!realme真我GT正式发布:2799元起售
- 苹果正为iPhone 12开发磁性电池组 可为手机无线充电
- 姚安娜首个代言摩卡汽车人舞蹈短片出炉
- 马斯克:全力支持狗狗币主要持有者出售货币 持仓太集中是问题
- 百度启动“2021好运中国年” 22亿福利项目
- 知乎启动首部科幻剧《寒梅工程2021》 概念片首次曝光
- 淘宝特价版注册“1元更香”商标,又一个新“节日”诞生了
- 美团与饿了么“鸡同鸭讲”后,又可以通过设置继续使用支付宝了?
- 库克笑嘻嘻!苹果明年或将迎来继iPhone 6后第二次换机大潮