快速了解ClickHouse!
简介
ClickHouse是一个开源列式数据库管理系统(DBMS),用于在线分析处理(OLAP):
列式存储:与传统的行式数据库不同,ClickHouse以列的形式存储数据,这使得在分析大量数据时能够获得更好的性能和压缩率。
高速查询:ClickHouse为分析大量数据而优化,可以执行复杂的查询,并在极短的时间内提供答案。
分布式处理:ClickHouse可以无缝地在多个节点上部署,提供水平扩展。它支持复制、分片和负载均衡。
数据压缩:由于列式存储的特点,ClickHouse提供了高效的数据压缩,从而节省存储空间并提高查询速度。
SQL支持:ClickHouse使用SQL作为查询语言,并提供了丰富的函数库,包括时间序列、聚合和字符串处理函数等。
实时处理:尽管ClickHouse主要是为OLAP场景设计的,但它还支持近实时数据插入和查询,使其在某些情况下也可用于在线事务处理(OLTP)。
开源与社区:ClickHouse是完全开源的,拥有一个活跃的开发和用户社区。
多种数据格式:ClickHouse支持多种数据格式,如Parquet、JSON、CSV等,这使得从其他系统迁移或导入数据变得非常容易。
与其他技术的集成:ClickHouse可以与多种其他技术(例如Kafka、HDFS等)集成,使其能够在各种环境中高效地工作。
简而言之,CK本质上就是DBMS,起源于mysql。重要特点就是:数据按列存储,适合于OLAP在线分析处理,查询列的速度非常之快,节省大量的IO资源。(其实和hudi有点像,hudi就是行写入、列查询)
同一列保存在同一个数据文件当中,便于数据的压缩存储!
这一点很好理解,同一列的数据类型(域)是一致的,想想看是各种类型都有的一行数据好压缩,还是一列相同类型的数据好压缩?结果显而易见!
本质上,CK的数据类型和C++相似,因为CK就使用C++写的。
ClickHouse 与表函数
ClickHouse的强大表函数支持增强了其与其他系统的互操作性,为用户提供了更多的灵活性和方便性。涉及到DBMS和大数据框架的整合,使得数据处理和分析变得更加高效和无缝。
表函数 (Table Function)
表函数是一种数据库函数,它返回一个可以像操作常规数据库表那样操作的行集。其主要目的是能够将函数的输出作为一个表来使用。这意味着我们可以使用SQL查询来读取和处理这些函数的输出。
ClickHouse 与表函数
ClickHouse的特点之一是其广泛的表函数支持。这些表函数允许管理员用户从各种数据源(例如文件、URL、外部数据库、大数据框架等)读取数据,并将这些数据作为表来处理。例如,管理员用户可以使用表函数从一个文件或HTTP URL中读取数据,然后直接在ClickHouse中对该数据进行查询,而无需先导入数据。
DBMS 和大数据框架的整合
ClickHouse为了提高灵活性和扩展性,提供了与其他DBMS和大数据框架的整合功能。例如,ClickHouse可以与Kafka、HDFS、MySQL等进行交互。表函数在这方面发挥了关键作用,它们使得从这些系统中读取数据变得异常简单。通过表函数,ClickHouse可以轻松地与其他系统进行交互,从而实现数据的即时查询和分析,而无需事先进行数据迁移或转换。
CK存储引擎及Primary Key
CK使用了一种名为MergeTree
的数据结构和存储引擎:
MergeTree存储引擎
数据结构: MergeTree 是由一系列有序的
parts
组成。每个part
包含了多个按照某种键(通常是 PRIMARY KEY)排序的granules
。
Parts 和 Granules
- 在ClickHouse中,数据被分成
parts
(部分)。每个part
包含多个granules
。可以将part
看作是granules
的集合。随着时间的推移,parts
可能会由于合并操作而变大。但不论part
的大小如何,它都是由granules
组成的。Granule
是MergeTree
表数据的最小物理单位。每个granule
包含一定数量的行。当我们说“块”,这与granule
是相似的概念,但granule
是ClickHouse的专用术语。- 物理上,每个
granule
包含固定数量的行(例如8192行,即8192条记录),但这个数字可能会因配置或其他因素而有所不同。
合并Parts
- 在数据写入ClickHouse时,首先写入小的granules,其实也相当于写入
parts
。随着时间的推移,ClickHouse会在后台运行合并操作,将小的parts
合并成大的parts
。这种合并操作可以提高查询性能并节省存储空间。- 合并操作: MergeTree 的命名来源于其后台自动进行的特性,即定期将小的
parts
合并为更大的parts
。这种合并操作旨在优化数据压缩并提高查询效率,因为数据库可以快速定位数据所在的位置。
PRIMARY KEY in ClickHouse
- 排序: 在ClickHouse中,
PRIMARY KEY
定义了数据的物理排序方式。当查询数据时,ClickHouse会使用这个排序信息来跳过那些不相关的数据块。- 不是唯一的: 与MySQL不同,ClickHouse中的
PRIMARY KEY
不保证唯一性。它只是一个排序和索引工具。- CK中如果不设定PK,那么创建表时会报错!不设定PK的情况下必须指定ORDER BY才行!所以可以理解为CK必须需要依赖于一种排序方式,而这种排序方式可以是PK,也可以是ORDER BY来提供。
为什么与MySQL中的PRIMARY KEY不同
- 目的不同: MySQL(以及其他传统的关系型数据库)中的
PRIMARY KEY
主要用于确保数据的唯一性和引用完整性。而ClickHouse的设计目标是查询速度和分析,所以PRIMARY KEY
在ClickHouse中主要用于数据排序和查询优化。- 数据模型: 由于ClickHouse是为OLAP场景设计的,它的数据模型与为在线事务处理(OLTP)设计的MySQL有所不同。在OLAP场景中,大量的数据聚合和分析比数据的唯一性更为重要。
CK的 PRIMARY KEY 和 稀疏索引
- 在ClickHouse中,
PRIMARY KEY
被用作稀疏索引。这意味着不是为每一行数据都保存索引项,而是为每个granule
保存一个索引项。这就是为什么一个PRIMARY KEY
对应多个行。
- 图中:左侧为pk,右侧为其对应的入口,其实通常来说同时也会存储row8192/16384/24576这样的最大值,这种设计选择为ClickHouse提供了查询性能的优势。由于它的目标是为OLAP和大数据分析优化,所以它偏好于范围查询而不是单行查询。为每个
granule
而不是每行保存索引项,使得索引更小、更快,而且更适合这种用途。
让我们通过CK中的块,进一步了解CK的主键:
块之间的顺序:
- 在ClickHouse中,每个
granule
的创建是基于插入的数据批次的。当一批数据被插入时,它们会首先按照PRIMARY KEY进行排序。排序后,数据会被划分为大小适中的granules
。每个granule
内部的数据都是有序的,因此,granules
之间也存在一个顺序。但这并不意味着所有granules
之间都有全局的严格排序,因为新的插入操作可能会引入新的granules
。- 当执行一个批量数据插入操作时,数据首先被缓存并按照PRIMARY KEY排序。一旦数据达到了一定的大小或时间阈值,它就会被刷入磁盘形成新的
granules
,并进一步形成新的parts
。这种批量处理方式优化了磁盘I/O操作,提高了数据插入的吞吐量和整体性能。
块合并:
1. ClickHouse的合并操作基于
MergeTree
家族中特定的表引擎策略。通常,合并操作考虑part的大小、年龄、数据的修改历史等因素。合并也有助于清除数据的过时版本,因为ClickHouse支持数据的版本控制。2. 当新数据被写入ClickHouse时,它的granule形式会被立即组成一个新的
part
。这是一个非常快速的操作,因为新写入的数据本质上已经形成了一个独立的part
。所以,它本身就已经是一个part
,并不需要额外的时间来将块转换为part
。3. 然而,后台的合并操作(将多个小
parts
合并为一个更大的part
)确实需要时间,因为这涉及到读取、合并和写入数据。这种合并操作是为了提高存储效率、查询性能和数据压缩。但对于新写入的数据,它们已经直接形成了新的part
,不需要等待。如图,part不是无限合并的,有150GB大小的限制。
MySQL的聚集索引与ClickHouse的PRIMARY KEY:
- MySQL中的聚集索引确实按照
PRIMARY KEY
来存储数据。但ClickHouse和MySQL的设计目标和使用场景有所不同。ClickHouse是为大数据分析优化的,而MySQL则更倾向于在线事务处理。- 在MySQL中,
PRIMARY KEY
确保了唯一性,这对于事务性操作是很有价值的,因为你经常需要基于唯一键来更新或删除特定的记录。而在ClickHouse中,数据通常是以批次写入并追加的方式插入的,而不是单行的插入、更新或删除。- ClickHouse中改变
PRIMARY KEY
的意义,是为了更好地服务于它的主要用例:大数据分析。其PRIMARY KEY
更多地作为一个优化查询性能的工具,而不是作为一个确保数据完整性的约束。
再理解二者PK的区别:
MySQL的PRIMARY KEY
(聚集索引)和ClickHouse的PRIMARY KEY
都能实现数据跳过和减少存储需求的效果,但它们是为了不同的工作负载而优化的。
数据跳过:MySQL的聚集索引确实允许它快速查找特定的行。但在大规模数据分析中,你经常需要处理大范围的数据,而不是单独的行。Mysql数据跳过过程请见文章Mysql底层执行过程及基于PK的“数据跳跃”-CSDN博客,ClickHouse的
PRIMARY KEY
是为了这种查询模式设计的,它可以让系统判断哪些数据块是与查询条件无关的,从而跳过大量数据。减少存储需求:虽然MySQL的聚集索引也按
PRIMARY KEY
排序存储数据,但由于它的行式存储模式,压缩效果不及ClickHouse。ClickHouse的列式存储结合数据排序可以实现更高效的数据压缩。
可以这么理解:MySQL的PRIMARY KEY
是全能型设计,旨在优化随机访问和事务性查询。而ClickHouse的PRIMARY KEY
是专攻型设计,特别优化了大数据分析的工作负载。
ClickHouse中数据写入和存储的过程
数据写入与排序:当新的一批数据写入ClickHouse时,它会首先按照
PRIMARY KEY
进行排序。形成granules:排序后的数据会被分割为大小适中的
granules
,通常每个granule
包含8192条记录(或其他预设的行数)。列式存储:每个
granule
内的数据会按列进行存储。也就是说,同一个granule
里,一列的所有数据都连续存放在一起,这对于压缩和查询效率都很有帮助。例如,如果有一个表有三列:A
,B
, 和C
,则granule
内的所有行的列A
的数据都存储在一起,紧接着是列B
的数据,然后是列C
的数据。
granule索引:对于每个
granule
,ClickHouse存储与PRIMARY KEY
列关联的最小和最大值。这些值表示了granule
内数据的范围,并被用作稀疏索引,以帮助加速范围查询。当执行查询时,通过检查每个granule
的最小和最大值,ClickHouse可以迅速确定哪些granules
可能包含查询结果。存储与压缩:
granules
会被压缩后存储在磁盘上,以节省存储空间。当新数据被写入ClickHouse时,它的granule形式会被立即组成一个新的
part,然后
将多个小parts
合并为一个更大的part。
总结
ClickHouse是一个高性能的分析数据库,适合实时或近实时的大数据查询。如果我们的目标是进行高速分析和查询,而不仅仅是数据存储和同步,那么使用ClickHouse可能会有帮助。我们可以将数据从数据库同步到ClickHouse,并使用ClickHouse的强大查询能力进行分析。
然而,如果只需要数据存储和简单的查询功能,直接使用Mysql / Hudi可能更加简洁和高效。只有需要高速、复杂的实时查询时,考虑使用ClickHouse。
相关文章:

快速了解ClickHouse!
简介 ClickHouse是一个开源列式数据库管理系统(DBMS),用于在线分析处理(OLAP): 列式存储:与传统的行式数据库不同,ClickHouse以列的形式存储数据,这使得在分析大量数据时…...

PythonWEB
文章目录 前端简介1. 什么是网页2. 网页的组成3. 网页的优势4. 前端三剑客5. 编写步骤6. HTTP协议 HTML51. HTML介绍2. 元素3. 使用4. 基本结构解析5. 常用标签文本标签容器标签列表标签表格标签表单标签 对于文件数据的提交需要满足以下两个条件:6. 标签分类 前端简…...

【工具问题】IDEA每次关闭的时候都会弹框显示closing project,然后弹框持续很久就像卡住了
idea关闭的时候出现问题 问题展示为什么会出现这种情况怎么解决 问题展示 我idea已经关闭了,但是这个弹框要持续很久才能关闭 为什么会出现这种情况 我的plugins原本是加载不出来的,所以我按照网上说法去做 怎么解决 file->setting,再如图选择…...

从瀑布模式到水母模式:ChatGPT如何赋能软件研发全流程
文章目录 前言内容简介作者简介专家推荐读者对象直播预告 前言 计算机技术的发展和互联网的普及,使信息处理和传输变得更加高效,极大地改变了金融、商业、教育、娱乐等领域的运作方式。数据分析、人工智能和云计算等新兴技术,也在不断地影响和…...

类变量/方法、main语法、代码块
一.类变量和方法 思维导图概览: 1.1类变量(静态变量) 1.什么叫做类变量/方法? ——给类中的成员属性或成员方法加上static关键字进行修饰,类变量/方法也叫做静态变量/方法,静态变量/方法被类的自身所有对…...
[SHCTF 校外赛道] crypto
终于都结束了,这些新生赛太漫长了。不过这个也还是有些难度的,好多整不来。抓紧时间整理一下。 week1 第1周基本是古典密码,古典和现代最大的区别是古典全靠猜,现在都是数学 立正 wl hgrfhg 4gNUx4NgQgEUb4NC64NHxZLg636V6CDBi…...

vue3从基础到入门(一)
文章目录 简介提升使用创建脚手架vite 常用Composition APIsetuprefreactive函数响应式vue2响应式vue3实现响应式 reactive对比ref注意计算属性computed函数 监视watch函数watchEffect函数 生命周期hook函数toRef 简介 2020年9月18日,Vue.js发布3.0版本,…...
枚举类型 表示不同的 HTTP 状态码和相应的错误消息
java web业务中经常用常量来表示不同的 HTTP 响应状态,比如 public enum AppHttpCodeEnum {// 成功段0SUCCESS(200,"操作成功"),// 登录段1~50NEED_LOGIN(1,"需要登录后操作"),LOGIN_PASSWORD_ERROR(2,"密码错误"),// TOKEN50~100TOKEN_INVALID…...

SAP 使用cl_gui_timer自动刷新屏幕的用法详解 <转载>
原文链接:https://blog.csdn.net/SAPmatinal/article/details/130483382 SAP 使用cl_gui_timer自动刷新屏幕的用法详解 这个类在初始化的时候会设置一个定时间隔,每隔这个时间就会触发一次FINISHED事件。利用这个类的特性,可以实现很多东西&…...

golang中的Interface接口 类型断言、接口赋值、空接口的使用、接口嵌套
Interface整理 文章目录 Interface整理接口嵌套接口类型断言类型判断 type-switch使用方法集与接口空接口实例 接口赋值给接口 接口是一种契约,实现类型必须满足它,它描述了类型的行为,规定类型可以做什么。接口彻底将类型能做什么࿰…...
使用设计模式省去大量的if-elsef分支
1.测试类 Testpublic void test7() {/*** 使用设计模式前*///模拟入参String name "?";if("张三".equals(name)){System.out.println("按照张三的策略执行的任务!");}else if ("李四".equals(name)){System.out.println("按照李…...

Tomcat安装与配置文件解读
简介 Tomcat是Apache软件基金会(Apache Software Foundation)项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在…...

计算机网络重点概念整理-第一章 计算机网络概述【期末复习|考研复习】
计算机网络复习系列文章传送门: 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 前言一、计算机网络概述1.1 计算机网络的定义:1.2 计算机网…...

Day 11 python学习笔记
模块 内置模块 random random:随机数模块 我们可以在解释器中看到其蕴含的方法 接下来我解释一些常用的方法: random.random( ) random.random( ) 返回0-1的随机数 [0,1) >>> random.random() 0.364183511476754 random.randint(n,m) r…...

HarmonyOS鸿蒙原生应用开发设计- 图标库
HarmonyOS设计文档中,为大家提供了独特的图标库,开发者可以根据需要直接引用。 图标库可以分为双色图标、填充图标、线性图标。具体分为 键盘、箭头、连接状态、媒体、人、设备、索引、通信、文件、物体与工具等。 整体分类 开发者直接使用官方提供的图标…...

微软bing大声朗读文档或网页卡顿老是中断,用离线的huihui就很流畅但没那么自然
默认的xiaoxiao_online好听,但卡顿,朗读功能确实受到了网络状态的影响。 大概率是网络问题。...

Java VMTranslator Part I
目录 堆栈运算命令 基本思路 核心代码 Parser Code Writer Main 实验结果,使用SimpleAdd、StackTest进行验证 内存访问命令 基本思路 核心代码 Parser Code Writer Main 实验结果,使用进行验证。对比生成的二进制代码文件。 用Java写一个翻…...
ES6带来那些js新特性?
ECMAScript 6(ES6),也称为 ECMAScript 2015,引入了许多重大的改进和新特性,以改善JavaScript语言的功能和可读性。以下是一些ES6中的主要改变和新特性: 1、let 和 const 声明: 引入了 let 和 const 关键字…...
js数组深拷贝汇总
1.for 循环实现数组的深拷贝 通过对数组的for循环,即可实现对数组的深拷贝了。 var arr [1,2,3,4,5] var arr2 copyArr(arr) function copyArr(arr) {let res []for (let i 0; i < arr.length; i) {res.push(arr[i])}return res }2.slice 方法实现数组的深…...

错误 LNK1112 模块计算机类型“x64”与目标计算机类型“X86”冲突
这个错误表明你在进行链接时,模块的计算机类型与目标计算机类型冲突。 在这里,“x64”代表64位系统,“X86”代表32位系统。 要解决这个问题,你需要确保你的所有模块(包括库文件和依赖项)都是与你的目标计…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...