列式数据库-以clickHouse为例

1、 列式数据库

列式数据库(Columnar Databases)与行式数据库(Row-Oriented Databases)显著不同,需要具体场景具体分析:
列式数据库 以字段为中心,字段聚合效率优先,将同列数据连续存储(如ClickHouse),专为分析型负载(OLAP) 优化,典型应用于大数据分析、商业智能(BI)等需聚合海量数据的场景 。
行式数据库以记录为中心,记录完整性优先,将单行数据连续存储(如MySQL),适用于 高频率事务处理 ,例如电商交易、普通应用程序等快速读写完整记录的场景 。

2、 列式数据库的优点

同一列的所有值连续存储在磁盘块中,例如所有"学生成绩"字段集中存储 。
I/O效率高 :查询仅需读取相关列,避免加载冗余数据 。
压缩率显著 :同列数据同质性强(如均为整数),可采用RLE编码(重复值压缩)、字典编码(有限值域优化)、差值压缩(时序数据)等算法,压缩率达 8:1至60:1(行式数据库仅3:1-5:1)。

但列式数据库的单行更新需修改多个分散列块,事务效率低 。

3、 列式数据库的适合场景

大规模分析查询 :数据仓库、BI报表(如Apache Parquet + Spark)。
高压缩需求 :归档数据、物联网时序数据(压缩比>30:1)。
只读/低频更新:历史日志分析、批量数据处理。

4、clickHouse

ClickHouse 是一个开源的列式数据库管理系统(DBMS),专注于在线分析处理查询(OLAP)。Yandex公首次开源于2016年, 其主要用于在大数据的场景下进行实时的数据分析。可以见官网

在 1 亿数据级体量的情况下,ClickHouse 的平均响应速度是MySQL 的 429 倍,由此可见列式数据库在高数据量场景下的卓越性能。

性能数据比对详见:https://benchmark.clickhouse.com/

4.1 clickHouse数据存储与索引

根据官网教程(https://clickhouse.com/docs/guides/creating-tables)创建一张表:

java 复制代码
CREATE TABLE helloworld.my_first_table
(
    user_id UInt32,
    message String,
    timestamp DateTime,
    metric Float32
)
ENGINE = MergeTree()
PRIMARY KEY (user_id, timestamp)

指定了一个复合主键(user_id, timestamp)

列字段相关的文件,每列都会有两个字段:

{column}.bin:列数据的存储文件,以列名+bin为文件名,默认设置采用 lz4 压缩格式;

{column}.cmrk:列数据的标记信息,记录了数据块在 bin 文件中的偏移量;

primary.cidx:这个是主键索引相关的文件的,用于存放稀疏索引的数据。通过查询条件与稀疏索引能够快速的过滤无用的数据,减少需要加载的数据量。
最小数据集 granule

表的列值在逻辑上被划分为 granule。多行数据为1 granule,granule 是为进行数据处理而流式传输到ClickHouse中的最小的不可分数据集。是始终读取(以流式传输方式并行读取)整个组(granule)行数据。每个 granule 分组的第一条数据会被写入到 primary.cidx 当作索引处理。

另外,有标记(.mrk)文件存储granule 在数据文件(.bin)中的存储位置。包含了两部分的信息,block offset 以及 granule offset。

因此,查询流程,先通过 primary.cidx 找到了对应数据所在 mark1,然后就可以对应的去 mrk 里面找对应的 block offset 和 granule offset。然后通过 block offset 找到该数据文件包含的压缩数据。文件块被解压缩到主内存中,随后granule offset 在未压缩的数据中定位对应的数据。

4.2 clickHouse联合主键查询

联合主键查询,与Mysql复合索引的最左原则类似,user_id, timestamp两个联合主键,如果where 条件里面只写了 user_id='xxx',可以使用二分查找法进行快速的索引;但如果只写了 timestamp='xxx',则会全表扫描。

4.3 clickHouse更新与删除

Clickhouse对update、delete的支持是比较弱,异步方式更新与删除,不保证原子性。
删除时 ,ClickHouse为删除的那一行的 _row_exists 列做标记,即逻辑删除,后续查询会排除已删除的行。

需要从磁盘中清理的,即物理删除,可以通过使用ALTER...DELETE操作:

java 复制代码
alter table  my_first_table delete where  user_id= 1155

更新时, 主键的列或者排序键的值不能被更改,使用ALTER... UPDATE语句:

java 复制代码
alter table  my_first_table UPDATE message ='AAA'  where  user_id= 1155

4.4 clickHouse总结

clickHouse在单独某几列的查询速度非常快,数据可压缩,索引使用稀疏索引的方式占用空间少。无事务,更新删除效率低。

参考:

https://blog.csdn.net/m0_61505785/article/details/149630180

https://blog.csdn.net/glpghz/article/details/136003917

https://baijiahao.baidu.com/s?id=1775813809050392712\&wfr=spider\&for=pc

https://www.cnblogs.com/think90/p/11443311.html

https://zhuanlan.zhihu.com/p/691497650

https://cloud.tencent.com/developer/news/1331267

相关推荐
dovens4 分钟前
PostgreSQL 中进行数据导入和导出
大数据·数据库·postgresql
IOT.FIVE.NO.14 分钟前
claude code desktop cowork报错解决和记录Workspace..The isolated Linux environment ...
linux·服务器·数据库
Rick199312 分钟前
mysql 慢查询怎么快速定位
android·数据库·mysql
科技小花7 小时前
全球化深水区,数据治理成为企业出海 “核心竞争力”
大数据·数据库·人工智能·数据治理·数据中台·全球化
X56618 小时前
如何在 Laravel 中正确保存嵌套动态表单数据(主服务与子服务)
jvm·数据库·python
虹科网络安全9 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
2301_7717172110 小时前
解决mysql报错:1406, Data too long for column
android·数据库·mysql
小江的记录本10 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
dvjr cloi10 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
dFObBIMmai11 小时前
MySQL主从同步中大事务导致的延迟_如何拆分大事务优化同步
jvm·数据库·python