当前位置: 首页 > news >正文

从底层原理上解释 ClickHouse 的索引

        ClickHouse 是一款高性能的列式数据库,它通过列式存储、稀疏索引、MergeTree 引擎等技术实现了极高的查询效率和吞吐量。索引是数据库中提高查询效率的关键机制之一。为了深入了解 ClickHouse 中的索引实现机制,我们将从底层原理、关键数据结构以及 ClickHouse 的源代码来解释其索引设计。

1. ClickHouse 的索引机制概览

        ClickHouse 的索引与传统数据库(如 MySQL、PostgreSQL 等)的 B-Tree 或哈希索引不同,它主要依赖于稀疏索引(sparse index)和分段索引(granularity index)来加速查询。由于 ClickHouse 的设计初衷是为大规模分析型查询场景服务,所以它的索引机制更适合扫描大批量数据,并通过减少不必要的磁盘 IO 来加速查询。

1.1 基础概念
  • 列式存储:ClickHouse 使用列式存储,也就是说数据按列而不是按行存储。在列式存储中,相同列的数据集中存储,使得读取少数列时非常高效。
  • 稀疏索引(Sparse Index):ClickHouse 使用的是一种稀疏索引,意味着它不会为每条记录都维护索引,而是根据数据块(block)来构建索引。每个数据块保存若干行(通常是 8192 行),索引只保存每个块的起始值。
  • 数据分段(Granularity):ClickHouse 采用了分段的概念,数据被分割成多个段,每个段内数据排序,并且有自己的索引。每个段的大小决定了查询时需要扫描的数据量。

2. MergeTree 引擎中的索引机制

    MergeTree 是 ClickHouse 中最重要的存储引擎之一。该引擎不仅支持高效的读写性能,还支持自动的分区和合并操作。

2.1 主键索引(Primary Key Index)

        在 MergeTree 表中,主键索引并不是传统意义上的唯一约束,而是用于优化查询的排序键。主键的索引由 稀疏索引 和 段内数据排序 组成。当表使用 ORDER BY 语句时,ClickHouse 会根据排序键为每个数据段构建稀疏索引。

  • 原理
    • 数据写入时按照主键排序(如果指定了 ORDER BY),每次插入新的数据块时,ClickHouse 会在磁盘上生成新的稀疏索引。
    • 每个稀疏索引条目对应一个数据块中的首行,索引条目记录该块的首个主键值以及其在数据文件中的位置。
    • 查询时,ClickHouse 使用索引跳过不相关的块,减少扫描的数据量。
2.2 索引的存储结构

主键索引会被存储在 .idx 文件中,索引文件以稀疏的方式记录每个数据块的起始位置。

  • 索引存储结构
    • 数据写入时,ClickHouse 为每个数据块生成主键索引。每个索引条目包含该块内数据的首个主键值以及相应的偏移量。
    • 主键值可以由多个列组成,ClickHouse 会为多列组合生成复合主键索引。
示例:创建 MergeTree 表
CREATE TABLE events
(event_date Date,event_time DateTime,user_id UInt32,event_type String
) 
ENGINE = MergeTree 
ORDER BY (event_date, user_id);

        在上面的例子中,ORDER BY (event_date, user_id) 表示 ClickHouse 会对表中的数据根据 event_date 和 user_id 进行排序,并为这些列创建主键索引。在查询时,ClickHouse 会利用这些主键索引来加速查询。

2.3 段式存储与索引

        ClickHouse 将数据分为多个段(part),每个段包含一定数量的行(默认 8192 行)。每个段内的数据按照指定的排序键(即 ORDER BY 中的列)进行排序,并为每个段创建稀疏索引。

  • 每个段的索引结构
    • 索引文件(.idx):稀疏索引,记录每个数据段中首行的主键值。
    • 数据文件(.bin):实际存储的列数据,列式存储的文件按列分开存储。
索引文件的结构:
.index file structure:
+--------------------+------------------+----------------+
| Primary Key Value   | Block Start Row  | Block Position |
+--------------------+------------------+----------------+

        当执行查询时,ClickHouse 通过索引文件定位数据块,然后只扫描与查询条件相关的块,从而极大地提升查询效率。

3. ClickHouse 的二级索引(Data Skipping Indexes)

        除了主键索引,ClickHouse 还支持 Data Skipping Index,也就是所谓的“跳过索引”。这种索引允许 ClickHouse 在查询时跳过那些不相关的块,而不需要扫描每一行。这在列上具有高度稀疏性或数据分布不均匀的场景下非常有用。

常用的跳过索引类型
  1. minmax 索引:记录每个数据段的最小值和最大值。对于范围查询,例如 WHERE column > x AND column < y,ClickHouse 可以跳过不在范围内的块。

    ALTER TABLE events ADD INDEX minmax_index 
    (user_id) TYPE minmax GRANULARITY 8192;
    
  2. bloom_filter 索引:用于高基数的数据列,例如字符串或 ID 字段。布隆过滤器可以快速过滤掉不可能匹配的数据块。

    ALTER TABLE events ADD INDEX bloom_filter_index 
    (event_type) TYPE bloom_filter GRANULARITY 8192;
    
  3. tokenbf_v1 索引:一种适用于包含大量词汇的字段(如文本)的布隆过滤器索引,它能够对包含某个词的查询进行加速。

    ALTER TABLE events ADD INDEX tokenbf_index 
    (event_type) TYPE tokenbf_v1(1000) GRANULARITY 8192;
    
跳过索引的实现原理

        当进行查询时,ClickHouse 会首先检查跳过索引,确定哪些数据块可以跳过,而不需要进行全表扫描。例如,在范围查询中,ClickHouse 可以通过 minmax 索引检查每个数据块的最小值和最大值,并直接跳过不满足条件的块。

4. ClickHouse 索引的底层代码分析

我们来看一下 ClickHouse 源代码中关于索引的部分,尤其是稀疏索引和数据跳过索引的实现。

4.1 稀疏索引实现

        稀疏索引的实现位于 MergeTreeData 类中,它管理了 MergeTree 表中的数据结构和索引创建过程。稀疏索引的构建逻辑主要通过 MergeTreeIndexGranularity 类来实现。

在 MergeTreeDataWriter 类中,数据块的写入和索引创建的关键代码如下:

// MergeTreeDataWriter.cpp
void MergeTreeDataWriter::writeBlock(const Block & block, ... )
{// 写入数据块writer.write(block);// 构建稀疏索引index_builder->add(block); 
}

        在写入数据块时,index_builder 会为每个数据块生成一个索引条目。索引条目中包含了该数据块的起始主键值和数据文件中的位置。

4.2 minmax 索引的实现

    minmax 索引是一种非常简单的跳过索引,它记录了每个数据块的最小值和最大值。在查询时,ClickHouse 可以通过检查 minmax 索引来跳过不符合条件的块。

minmax 索引的创建和检查逻辑位于 MergeTreeDataPart 类中,代码如下:

// MergeTreeDataPart.cpp
bool MergeTreeDataPart::minmax_index_check(const Field & value) const
{// 检查当前块的最小值和最大值return (value >= min_value && value <= max_value);
}

在查询执行时,ClickHouse 会检查 minmax 索引,跳过那些不在查询范围内的块。

5. 总结

        ClickHouse 的索引机制主要依赖于 稀疏索引 和 跳过索引,这些索引能够大幅减少查询时的数据扫描量。不同于传统数据库的行式存储索引,ClickHouse 的索引设计更加适合批量分析场景,利用稀疏索引减少 IO,通过跳过索引加速查询。底层实现中,MergeTree 系列存储引擎通过维护稀疏索引来定位数据块,同时 minmax 和 bloom_filter 等跳过索引进一步优化查询性能。

        通过这些索引机制,ClickHouse 能够在大规模数据处理场景下保持极高的查询性能,同时支持复杂的查询和分析操作。

相关文章:

从底层原理上解释 ClickHouse 的索引

ClickHouse 是一款高性能的列式数据库&#xff0c;它通过列式存储、稀疏索引、MergeTree 引擎等技术实现了极高的查询效率和吞吐量。索引是数据库中提高查询效率的关键机制之一。为了深入了解 ClickHouse 中的索引实现机制&#xff0c;我们将从底层原理、关键数据结构以及 Clic…...

9.20-使用k8s部署wordpress项目

部署wordpress项目 部署mariadb # 启动docker进程systemctl start docker​# 拉取三个镜像​docker pull nginx:alpinedocker pull wordpress:latestdocker pull mariadb:latest​# 保存三个镜像​cddocker save -o wordpress.tar wordpress:latestdocker save -o mariadb.tar…...

OSPFv3协议几类LSA介绍

OSPFv3协议介绍 与OSPFv2相比&#xff0c;OSPFv3在工作机制上与OSPFv2基本相同&#xff1b;但为了支持IPv6地址格式&#xff0c;OSPFv3对OSPFv2做了一些改动。OSPFv3基于OSPFv2基本原理增强&#xff0c;是一个独立的路由协议&#xff08;v3不兼容v2&#xff09;协议号仍然是89…...

煤矿智慧矿井数据集 (1.煤矿采掘工作面智能分析数据集2.煤矿井下钻场智能分析数据集 )

智慧矿井智能分析数据集 数据1&#xff1a;数据1包含煤矿采掘工作面工人安全帽检测&#xff0c;工人行为检测&#xff08;行走&#xff0c;站立&#xff0c;坐&#xff0c;操作&#xff0c;弯腰&#xff0c;靠&#xff0c;摔&#xff0c;爬&#xff09;&#xff0c;液压支撑防护…...

举例说明协方差的数学公式计算步骤以及皮尔逊相关系数数学公式的计算步骤

例子&#xff1a;协方差的计算步骤 协方差是用于衡量两个随机变量之间的线性相关性的统计量。它表示两个变量如何一起变化。如果协方差为正&#xff0c;表示两个变量倾向于同方向变化&#xff1b;如果为负&#xff0c;表示它们倾向于反方向变化。 下面我们将通过一个具体的例…...

2024/9/16论文赏析(均为1区或顶刊

Labeled-to-Unlabeled Distribution Alignment for Partially-Supervised Multi-Organ Medical Image Segmentation 代码链接&#xff1a;GitHub - xjiangmed/LTUDA 论文链接&#xff1a;Labeled-to-Unlabeled Distribution Alignment for Partially-Supervised Multi-Organ …...

IDEA 2024.3 EAP新特征早览!

0 前言 IntelliJ IDEA 2024.3 第一个 EAP 版本已发布&#xff0c;提前体验 下一个重大版本的一部分改进。 持续关注 EAP 更新&#xff0c;未来几周内将推出更多 IntelliJ IDEA 新功能。尝试这些新功能&#xff0c;分享您的反馈&#xff0c;共同完善 IDE。 1 AI 助手 1.1 内…...

如何在安卓設備上更換IP地址?

IP地址是設備在網路中的唯一標識&#xff0c;通過IP地址&#xff0c;網路能夠識別並與設備進行通信。本文將詳細介紹在安卓設備上更換IP地址的幾種方法。 在安卓設備上更換IP地址的方法 1. 使用Wi-Fi網路更換IP地址 最簡單的方法是通過Wi-Fi網路更換IP地址。步驟如下&#x…...

LINUX网络编程:TCP(1)

目录 1.认识Tcp的报头 2.确认应答机制&#xff08;ACK&#xff09; 序号与确认序号 捎带应答 3.超时重传机制 4.Tcp连接管理 三次握手 为什是三次握手 四次挥手 理解TIMEWAIT 1.认识Tcp的报头 源端口和目的端口号没什么说的 32位的序号和确认序号&#xff0c;之后会介…...

基于PHP的新闻管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpMySQL的新闻管理系统。…...

6.C++程序中的基本数据类型

数据类型是指在C中用于声明不同类型变量或函数的一个系统或抽象或者是一个分类&#xff0c;它决定了变量存储占用的内存空间以及解析存储的位模式。其实数据类型可以理解为固定内存大小的别名&#xff0c;是创建变量的模具&#xff0c;具体使用哪种模具&#xff08;包括自定义&…...

oracle 11g写一个判断是否是身份证的函数,函数名称为:FUN_IS_IDENNO

下面是一个用于判断是否是身份证号码的Oracle 11g函数&#xff08;FUN_IS_IDENNO&#xff09;。身份证号码通常为18位&#xff08;或者旧的15位&#xff09;&#xff0c;前17位为数字&#xff0c;第18位为数字或字母X&#xff0c;并且需要符合一定的规则&#xff0c;例如出生日…...

如何使用Spring Cloud Gateway搭建网关系统

使用Spring Cloud Gateway搭建网关系统是一个涉及多个步骤的过程&#xff0c;主要包括创建Spring Boot项目、添加 Spring Cloud Gateway依赖、配置路由规则以及运行和测试网关。以下是详细的步骤&#xff1a;一、创建Spring Boot项目 选择工具&#xff1a; 可以使用Spring Ini…...

油烟机制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

油烟机制造5G智能工厂物联数字孪生平台&#xff0c;是智能制造与信息技术的深度融合产物。数字孪生工业互联平台通过部署在工厂各个环节的传感器和设备&#xff0c;实时采集、分析和处理生产过程中的海量数据&#xff0c;构建出高度逼真的数字孪生模型。这一模型不仅能够真实反…...

《拿下奇怪的前端报错》序章:报错输出个数值数组Buffer(475) [Uint8Array],我来教它说人话!

作为前端开发者&#xff0c;你可能会遇到过一些奇奇怪怪的报错&#xff08;相信我你早晚会遇到&#xff09;&#xff0c;关键是它未给出具体错误的位置&#xff0c;或者是一些很奇怪的信息。 我以前都是还原代码&#xff0c;然后找到错误的位置。或者是瞎弄一通&#xff0c;测试…...

Docker 里面按照ifconfig

1. 进入Docker 容器内部 docker exec -it xxx bash2. 安装 net-tools iputils-ping apt-get update && apt-get install -y net-tools apt-get update && apt-get install -y iputils-ping 3. 执行ifconfig 执行ping...

DOS(Disk Operating System,磁盘操作系统)常用指令

目录 背景: 早期探索: DOS之父&#xff1a; 发展历程&#xff1a; 常用指令&#xff1a; 进入命令&#xff1a; 操作1.进入和回退&#xff1a; 操作2.增、删&#xff1a; 操作3.其它&#xff1a; 总结: 背景: 早期探索: DOS(Disk Operating System,磁盘操作系统)在…...

VSCode集成Python环境搭建配置详细步骤

1. 安装VSCode 在开始我们的Python编程之旅前,首先需要准备好我们的开发工具——Visual Studio Code,简称VSCode。VSCode是一款由微软开发的轻量级但功能强大的源代码编辑器,支持多种编程语言,并且拥有丰富的扩展生态系统。接下来,我们将一步步教你如何下载、安装以及汉化…...

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【扩展组件】上

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核&#xff08;LiteOS-M&#xff09; 轻量系统内核&#…...

Windows【环境 01】服务器系统重装后的服务恢复(ES\Redis\Jafka\Tomcat)环境变量和服务注册

服务器系统重装后的服务恢复 1.原因2.问题处理2.1 JDK2.2 Elasticsearch2.3 Redis2.4 Jafka2.5 Tomcat 3.总结 1.原因 Windows 服务器系统盘损坏&#xff0c;换了硬盘并重做了系统&#xff0c;其他磁盘未损坏但安装的服务无法正常运行了&#xff0c;包括&#xff1a; Elastic…...

T型翼/尾板导向的穿浪双体船姿态控制【附代码】

✨ 长期致力于穿浪双体船、T型翼、尾板、多自由度姿态控制、舒适性评估研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;动态水翼升力模型与耦合运动方…...

Unity UGUI轻量UI框架:200行代码实现零GC界面管理

1. 为什么还要自己手写UI框架&#xff1f;——当UGUI原生方案开始“卡脖子”很多人看到这个标题第一反应是&#xff1a;“都2024年了&#xff0c;还手写UI框架&#xff1f;Asset Store里几十个成熟方案&#xff0c;NGUI、FairyGUI、TextMeshPro配套的UI系统一抓一大把&#xff…...

CentOS 7下‘Development Tools’和‘开发工具’组有区别吗?实测告诉你答案

CentOS 7下‘Development Tools’与‘开发工具’的隐藏关联&#xff1a;技术细节全解析在Linux系统管理中&#xff0c;yum的软件包组功能一直是个既实用又充满谜团的领域。特别是当系统语言环境与软件包元数据语言不一致时&#xff0c;开发者们常常会遇到一个有趣的现象&#x…...

癫痫手术精准定位:基于脑电信号昼夜节律与多生物标志物的机器学习分析框架

1. 项目概述&#xff1a;当机器学习遇见脑电信号&#xff0c;如何让癫痫手术更精准&#xff1f;作为一名长期耕耘在生物医学信号处理与机器学习交叉领域的工程师&#xff0c;我常常思考如何将算法模型从实验室的“玩具”变成临床医生手中可靠的“手术刀”。癫痫&#xff0c;这个…...

Obsidian PDF++:如何在Obsidian中实现PDF与笔记的无缝双向链接?

Obsidian PDF&#xff1a;如何在Obsidian中实现PDF与笔记的无缝双向链接&#xff1f; 【免费下载链接】obsidian-pdf-plus PDF: the most Obsidian-native PDF annotation & viewing tool ever. Comes with optional Vim keybindings. 项目地址: https://gitcode.com/gh_…...

IPD的势、道、法、术、器

目录 简介 一、势&#xff1a;为什么 IPD 是必然选择&#xff1f; 二、道&#xff1a;IPD 的底层哲学 三、法与术&#xff1a;从战略到执行的具体路径 四、器&#xff1a;让流程真正落地的工具与组织 不是每家公司都需要全套 IPD&#xff0c;但每家公司都需要 IPD 思维 简…...

Lampiao 靶场

Lampiao 靶场完整渗透解析一、靶场环境信息攻击机&#xff08;Kali&#xff09;IP&#xff1a;192.168.146.128靶机 IP&#xff1a;192.168.146.129目标&#xff1a;获取靶机 root 权限与 flag二、步骤 1&#xff1a;信息收集&#xff08;端口与服务扫描&#xff09;nmap -p- -…...

新手村任务:成为一个架构师需要哪些装备?

新手村任务:成为一个架构师需要哪些装备? 一、前言 如果你刚入行不久,想成为一名架构师,那这篇文章就是为你写的。 我们把成为架构师比作一个RPG游戏,你是主角,需要收集各种装备、刷经验、升级技能。 新手村的第一个任务就是:了解你需要哪些装备。 二、架构师技能树…...

Sora 2原生接入Unity 6.0:5步完成神经渲染管线嵌入,实测帧率提升47%(附GitHub认证插件)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Sora 2与Unity整合 Sora 2作为新一代AI视频生成引擎&#xff0c;其开放API设计天然支持与实时3D引擎的深度协同。Unity 2023.2版本通过URP&#xff08;Universal Render Pipeline&#xff09;与C# Job System提…...

VMware ESXi 9.1.0.0集成NVME+网卡驱动版发布|新特性+驱动集成+部署升级+FAQ全指南

一、ESXi 9.1.0.0 正式版核心新特性 VMware ESXi 9.1.0.0&#xff08;2026 年 5 月发布&#xff09;是 vSphere 9.1 核心组件&#xff0c;聚焦硬件兼容扩展、性能跃升、安全加固、运维简化四大方向&#xff0c;重点强化 NVMe 存储与网卡生态适配&#xff0c;以下为关键更新&am…...