文章目录

  • 1.概述
  • 2.为什么要有LowCardinality
  • 3.做个小实验
  • 4.低基数的背后

1.概述

转载:https://www.jianshu.com/p/f361e7cfc8b3

2.为什么要有LowCardinality

在常见数据库系统的类型体系中,字符串是最灵活、表意性最强的类型,但是存储成本无疑也最高。ClickHouse提供了两种简单字符串的更优的存储方式,即:

  1. 存储固定长度(按字节数计)字符串的FixedString类型,
  2. 以及将字符串转为定长整形枚举值的Enum类型。

但是,我们平时见到的字符串绝大多数都是变长的,只有哈希值、IP等少数种类适合用FixedString存储;并且数据的定义域可能会经常变动,频繁修改Enum字段来增加枚举值也显然不可行。因此,ClickHouse又提供了第三条路,即LowCardinality——“低基数”类型。顾名思义,它适合长度和定义域都可变,但总体基数不是特别大的列。

根据官方文档,低基数是一种修饰类型,即用法为LowCardinality(type)。其中type表示的原始类型可以是String、FixedString、Date、DateTime,以及除了Decimal之外的所有数值类型。但是,LowCardinality的设计初衷就是为了优化字符串存储,修饰其他类型的效率未必会更高,所以下面只考虑LowCardinality(String)的情况。

  1. LowCardinality(Type),是一种数据类型上的字典编码封装。LowCardinality(String),别名StringWithDictionary,是最常见的LowCardinality类型。
  2. 使用LowCardinality编码的字段,在底层数据存储上做了修改。
  3. 适用场景:适用于原始string字段冗长且去重后的计数值<1000w
  4. 优势:使用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)类型相关推荐

  1. 聊聊ClickHouse中的低基数LowCardinality类型

    原文链接????:https://www.jianshu.com/p/f361e7cfc8b3 2020年快要过去了,写博客的习惯还是得捡起来.最近刚刚忙完搬家的事情,抽出一点时间简单聊两句. 为什么 ...

  2. 一文讲懂图像处理中的低通、高通、带阻和带通滤波器

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 空间域和频域滤波器通常分为四种类型的滤波器--低通.高通.带阻和带 ...

  3. Nat. Mach. Intell. | 基于神经网络的迁移学习用于单细胞RNA-seq分析中的聚类和细胞类型分类...

    今天给大家介绍由美国宾夕法尼亚大学佩雷尔曼医学院生物统计学,流行病学和信息学系Jian Hu等人在<Nature Machine Intelligence>上发表了一篇名为"It ...

  4. 可以获取python整数类型帮助的是什么-下列选项中可以获取Python整数类型帮助的是...

    [单选题]关于 Python 语言的特点,以下选项中描述错误的是 [单选题]下面代码的输出结果是: s1 = "The python language is a scripting lang ...

  5. 详解音视频直播中的低延时

    高泽华,声网 Agora 音频工匠,先后在中磊电子.士兰微电子.虹软科技主导音频项目.任职 YY 期间负责语音音频技术工作.在音乐.语音编解码方面有超过十年的研发经验. 音视频实时通讯的应用场景已经随 ...

  6. 【CV】一文讲懂图像处理中的低通、高通、带阻和带通滤波器

    空间域和频域滤波器通常分为四种类型的滤波器--低通.高通.带阻和带通滤波器.在本文中,我们为每一种滤波器提供了注释.代码示例和图像输出. 滤波器类型 低通滤波器:只允许通过低频细节,衰减高频细节.例如 ...

  7. java是如何实现原语的_Java中的低GC:使用原语而不是包装器

    java是如何实现原语的 总览 有两个很好的理由在可能的地方使用原语而不是包装器. 明晰. 通过使用原语,您可以清楚地知道null值是不合适的. 性能. 使用原语通常更快. 清晰度通常比性能更重要,并 ...

  8. Java中的低GC:使用原语而不是包装器

    总览 有两个很好的理由在可能的地方使用原语而不是包装器. 明晰. 通过使用原语,您可以清楚地知道null值是不合适的. 性能. 使用原语通常更快. 清晰度通常比性能更重要,并且是使用它们的最佳理由. ...

  9. 在c语言中出现的int错误类型,【揭秘】C语言类型转换时发生了什么?

    原标题:[揭秘]C语言类型转换时发生了什么? ID:技术让梦想更伟大 作者:李肖遥 在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统,我们常用的算术类型包括两种类型:整数类型和浮 ...

最新文章

  1. MECARD格式的电子名片简单介绍
  2. 今天收到IBM cat 测试
  3. 【Groovy】MOP 元对象协议与元编程 ( Groovy 类内部和外部分别获取 metaClass | 分析获取 metaClass 操作的字节码 | HandleMetaClass 注入方法 )
  4. 搞明白这八个问题,Linux系统就好学多了
  5. golang包管理解决之道——go modules初探
  6. python编程游戏手机版_利用Python开发手机同款游戏:开心消消乐
  7. [云炬创业基础笔记]第二章创业者测试8
  8. Struts 1高级应用
  9. kafka java客户端消息的分区与缓存发送
  10. “我爱淘”第二冲刺阶段Scrum站立会议4
  11. 目标检测(十八)--FPN
  12. 【论文撰写和程序员常用软件】
  13. 路由器与交换机的区别与联系
  14. python多元线性回归报错(assert pytype not in (tokenize.NL, tokenize.NEWLINE))
  15. 大数据的兴起,数据科学家的崛起
  16. linux卸载exe文件怎么恢复,linux中误删除程序包恢复实例
  17. 从零开始写项目第三篇【在线聊天和个人收藏夹】
  18. CAN IP SjA1000ip核 verilog写的 项目以在稳定的用
  19. 医院网络营销到底该怎么做
  20. 学c语言把电脑弄坏了,一不小心把学校的电脑弄坏了怎么样写检讨四百字

热门文章

  1. 百度2021年Q2净利润54亿元,智能云收入同比增71%
  2. 最便宜的骁龙888旗舰机!realme真我GT正式发布:2799元起售
  3. 苹果正为iPhone 12开发磁性电池组 可为手机无线充电
  4. 姚安娜首个代言摩卡汽车人舞蹈短片出炉
  5. 马斯克:全力支持狗狗币主要持有者出售货币 持仓太集中是问题
  6. 百度启动“2021好运中国年” 22亿福利项目
  7. 知乎启动首部科幻剧《寒梅工程2021》 概念片首次曝光
  8. 淘宝特价版注册“1元更香”商标,又一个新“节日”诞生了
  9. 美团与饿了么“鸡同鸭讲”后,又可以通过设置继续使用支付宝了?
  10. 库克笑嘻嘻!苹果明年或将迎来继iPhone 6后第二次换机大潮