Clickhouse的联合索引

Clickhouse 有了单独的键索引,为什么还需要有联合索引呢?了解过mysql的兄弟们应该都知道这个事。
对sql比较熟悉的兄弟们估计看见这个联合索引心里大概有点数了,不过clickhouse的联合索引相比mysql的又有些不一样了,mysql 很遵循最左匹配原则,但是clickhouse 又似乎有些不一样,具体哪里不一样呢,那么我们还是和上一篇 Q220240407–clickhouse 中的索引大白话一样,通过引用这张表hits_UserID_URL 来揭开下这个谜底。

一:联合索引
回到hits_UserID_URL的建表语句如下,我们当时创建表的时候,我们的主键就指定了UserID 和URL 如下:

CREATE TABLE hits_UserID_URL
(
UserID UInt32,
URL String,
EventTime DateTime
)
ENGINE = MergeTree
PRIMARY KEY (UserID, URL)
ORDER BY (UserID, URL, EventTime);
这样的主键大于1的情况,生成的那个primary.idx 索引文件(参考上一篇) 也就是会每一行都会生成n列记录(n>1),这样的索引文件我们就可以称之为联合索引文件是吧,故而UserID 和URL就形成了一个联合索引。其实为什么需要联合索引呢?那肯定是说在实际业务中这两个列经常放在一起查询,所以才会考虑给这两个列加索引。

但是联合索引的效果就真的好吗,这个取决于第一列索引的基数,什么是基数呢?说白了,就是某个列的值去重之后的个数,如果个数多说明基数高,如果个数少就说明基数低;那为什么联合索引的效果是取决于基数呢?因为联合索引在找数据的时候是使用排除搜索法的,下面我们来讲讲排除搜索法

1.1: 排除搜索法

排除搜索法顾名思义就是排除掉一些数据,然后搜索一波:

因为userId 和url 是按照字典顺序升序排列的,假如左边的键userID 的基数比较低,那么相同的userId可能会分布在很多的grandule 里面,也就可能分布在索引标记上,如下所示:

在这里插入图片描述

所以假如我们查询url <=w3 的数据,那么我们就可以看看相邻的两个grandule的最后一个url的值和第一个url的值;如果第一个url的值是w3, 第二个url 的值是w4,那么我们需要搜索的grandule 就只有前面的第一个grandule 和 之前的grandule 里面了,如法炮制,对着前面的所有的grandule,使用二分法,就可以在小于等于 o(logn)的时间复杂度找到对应的grandule;而且需要加载的grandule 非常少,这个效率挺高

但是,哈哈哈,凡事都怕但是,在实际生产环境中,userID和url的基数可能都很高,那么相同的userID 值可能就不会分布在多个表行和grandule 中,所以索引文件中的url 值就不太可能单调递增,如下所示:在这里插入图片描述

这个时候使用排除搜索法估计就要全表扫描了,使用不了二分法了;这个查询效率就贼低了,所以如果我们需要提高查找效率,就要使用多个主键索引了,而不是单纯的用联合索引。

二: 使用多个主键索引

2.1: 创建另一张表

最常见的方法就是我们再建另一张表,这张表的主键索引我们设置为url,如下所示:

CREATE TABLE hits_URL_UserID
(
UserID UInt32,
URL String,
EventTime DateTime
)
ENGINE = MergeTree
PRIMARY KEY (URL, UserID)
ORDER BY (URL, UserID, EventTime)
SETTINGS index_granularity = 8192, index_granularity_bytes = 0;

INSERT INTO hits_URL_UserID
SELECT * from hits_UserID_URL;

OPTIMIZE TABLE hits_URL_UserID FINAL;
这个当然可以加快查询,但是如果我们的系统已经上线了的话,这个改动还要应用系统那边改,不太实用

2.2: 使用物化视图

我们可以使用物化视图,不改动原表的情况下,如下所示:

CREATE MATERIALIZED VIEW mv_hits_URL_UserID
ENGINE = MergeTree()
PRIMARY KEY (URL, UserID)
ORDER BY (URL, UserID, EventTime)
POPULATE
AS SELECT * FROM hits_UserID_URL;

使用populate 的关键字是让原表的所有值钱的数据都导入这个物化视图,后续有的数据也会同步到这个物化视图;

但是这个的麻烦点也和刚刚的第一种方法一样,需要应用系统改动适配查询物化视图表,但是物化视图在做聚合方面很有用,如下所示:

–agg+物化视图本地表
–drop table if exists glab.bi_dws_lbs_adapter_agg_mv_local on cluster glab_cluster;

create materialized view glab.bi_dws_lbs_adapter_agg_mv_local on cluster glab_cluster(
id String,
idType AggregateFunction(argMax, String, UInt64 ),
geohash AggregateFunction(argMax, String, UInt64 ),
locType AggregateFunction(argMax, Int64, UInt64 ),
wifimac AggregateFunction(argMax, String, UInt64 ),
ip AggregateFunction(argMax, String, UInt64 ),
baseStation AggregateFunction(argMax, String, UInt64 ),
connectType AggregateFunction(argMax, Int64, UInt64 ),
equipmentId AggregateFunction(argMax, String, UInt64 ),
time AggregateFunction(max, UInt64 )
)
engine = AggregatingMergeTree()
partition by tuple()
order by id
as
select
id,
argMaxState ( id_type, ts ) AS idType,
argMaxState ( geohash12, ts ) AS geohash,
argMaxState ( loc_type, ts ) AS locType,
argMaxState ( wifimac, ts ) AS wifimac,
argMaxState ( ip, ts ) AS ip,
argMaxState ( base_station, ts ) AS baseStation,
argMaxState ( connect_type, ts ) AS connectType,
argMaxState ( equipment_id, ts ) AS equipmentId,
maxState( ts ) AS time
from glab.bi_dws_lbs_adapter_local
where geohash12 != ‘’ AND geohash12 IS NOT NULL
group by id;

–agg+物化视图集群表
CREATE TABLE glab.bi_dws_lbs_adapter_agg_mv on cluster glab_cluster as bi_dws_lbs_adapter_agg_mv_local
ENGINE = Distributed(‘glab_cluster’, ‘glab’, ‘bi_dws_lbs_adapter_agg_mv_local’, murmurHash3_32(id))

参考链接:https://cf.cloudglab.cn/pages/viewpage.action?pageId=226211113

2.3: 使用投影projection

上述两个方法都是需要应用系统适配,但是这个projection 就很好的解决了这个问题,BI这边改动就行,不需要应用改动,如下所示:

ALTER TABLE hits_UserID_URL
ADD PROJECTION prj_url_userid
(
SELECT *
ORDER BY (URL, UserID)
);

ALTER TABLE hits_UserID_URL
MATERIALIZE PROJECTION prj_url_userid; (使用materalize 是为了让原始的数据形成另一个索引)

所以当系统查询慢的情况下,如果就是因为联合索引的问题,我们可以使用projection,成本最小;如果需要查询诸如max(ts) 的geohash ,那就要用到物化视图了。

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

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

相关文章

深入解析Spring Boot的application.yml配置文件

目录 引言Spring Boot配置文件简介 application.yml的优点 基本结构与语法 YAML语法基础Spring Boot中application.yml的基本结构 常见配置项详解 服务器配置数据源配置日志配置其他常见配置 环境配置与Profile 多环境配置激活Profile 高级配置与技巧 属性的占位符替换自定义配…

Spring源码二十:Bean实例化流程三

上一篇Spring源码十九&#xff1a;Bean实例化流程二中&#xff0c;我们主要讨论了单例Bean创建对象的主要方法getSingleton了解到了他的核心流程无非是&#xff1a;通过一个简单工厂的getObject方法来实例化bean&#xff0c;当然spring在实例化前后提供了扩展如&#xff1a;bef…

第5章-组合序列类型

#全部是重点知识&#xff0c;必须会。 了解序列和索引|的相关概念 掌握序列的相关操作 掌握列表的相关操作 掌握元组的相关操作 掌握字典的相关操作 掌握集合的相关操作1&#xff0c;序列和索引 1&#xff0c;序列是一个用于存储多个值的连续空间&#xff0c;每一个值都对应一…

升级之道:精通Conda的自我升级艺术

升级之道&#xff1a;精通Conda的自我升级艺术 引言 Conda是Python和其他科学计算语言的强大包管理器&#xff0c;它不仅管理着包的安装和依赖&#xff0c;还负责自身的更新。随着开源社区的不断发展&#xff0c;Conda定期发布新版本以修复已知问题、增加新功能和提高性能。本…

[面试爱问] https 的s是什么意思,有什么作用?

HTTPS 中的 "S" 代表 "Secure"&#xff0c;即安全的意思。HTTPS&#xff08;全称是 HyperText Transfer Protocol Secure&#xff09;是HTTP&#xff08;HyperText Transfer Protocol&#xff09;的安全版本&#xff0c;主要作用是为互联网通信提供安全保护…

灵活多变的对象创建——工厂方法模式(Python实现)

1. 引言 大家好&#xff0c;又见面了&#xff01;在上一篇文章中&#xff0c;我们聊了聊简单工厂模式&#xff0c;今天&#xff0c;我们要进一步探讨一种更加灵活的工厂设计模式——工厂方法模式。如果说简单工厂模式是“万能钥匙”&#xff0c;那工厂方法模式就是“变形金刚”…

生成式人工智能:助攻开发者还是取代开发者?

引言 近年来&#xff0c;生成式人工智能&#xff08;AIGC&#xff09;在软件开发领域掀起了一场革命&#xff0c;为开发者带来了全新的工具和可能性。从代码生成、错误检测到自动化测试&#xff0c;AI正在以各种方式改变着开发者的工作方式。然而&#xff0c;这也引发了人们对开…

Python采集京东标题,店铺,销量,价格,SKU,评论,图片

京东的许多数据是通过 JavaScript 动态加载的&#xff0c;包括销量、价格、评论和评论时间等信息。我们无法仅通过传统的静态网页爬取方法获取到这些数据。需要使用到如 Selenium 或 Pyppeteer 等能够模拟浏览器行为的工具。 另外&#xff0c;京东的评论系统是独立的一个系统&a…

offer题目33:判断是否是二叉搜索树的后序遍历序列

题目描述&#xff1a;输入一个整数数组&#xff0c;判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。例如&#xff0c;输入数组{5,7,6,9,11,10,8},则返回true,&#xff0c;因为这个整数是下图二叉搜索树…

c++内存管理(上)

目录 引入 分析 说明 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 引入 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1…

集训day3:并查集

一、目录 1.并查集模版 2.并查集的理解和应用 二、正文 1.并查集模版 P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 2.并查集的理解与应用 (1).并查集与联通块数量 P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) P1656 炸…

数图助推朝阳佳惠辽宁华联开启数字化导航、精细化管理新纪元!

近期&#xff0c;辽宁省著名零售企业朝阳佳惠与辽宁华联&#xff0c;秉持创新精神&#xff0c;大胆尝试&#xff0c;在品类空间管理方面推出了创新举措。引入了先进的数图可视化陈列管理系统&#xff0c;通过智能化、直观化的方式优化商品布局。此举不仅大幅提高了商品管理的效…

去除各种软件弹窗教程

清羽弹窗 在mutil/OnlineDialog/onPostExecute前 添加return-void Arm弹窗 第一步&#xff0c;提取安装包 第二步&#xff0c;搜索代码Ljava/io/DataOutputStream;->flush()V 第三步&#xff0c;往上看找到 .registers 10 在下面加return-void 云注入弹窗 第一种方法:dex搜…

Sql 导入到 Excel 工具

Sql 导入到 Excel 工具 这个VBA宏的步骤如下&#xff1a; 通过文件对话框选择SQL文件。读取文件内容。解析文件中的每一行&#xff0c;如果包含“insert into”&#xff0c;则提取表名。检查是否已经存在以表名命名的工作表&#xff0c;如果不存在则创建新的工作表。将数据插…

element-ui封装分页组件:实现首页、上一页、下一页、末页、跳转按钮

首页、上一页、下一页、末页、跳转按钮 因为el-pagination只有一个插槽&#xff0c;所以通过两个el-pagination插槽分别加入首页、末页按钮&#xff0c;再拼接这两个el-pagination的方式来实现首页、末页按钮跳转按钮不用加事件&#xff0c;如果el-pagination修改了前往的页数…

【work】AI八股-神经网络相关

Deep-Learning-Interview-Book/docs/深度学习.md at master amusi/Deep-Learning-Interview-Book GitHub 网上相关总结&#xff1a; 小菜鸡写一写基础深度学习的问题&#xff08;复制大佬的&#xff0c;自己复习用&#xff09; - 知乎 (zhihu.com) CV面试问题准备持续更新贴 …

VOI(Virtual Operating System Infrastructure,虚拟操作系统基础架构)

VOI&#xff08;Virtual Operating System Infrastructure&#xff0c;虚拟操作系统基础架构&#xff09;架构在桌面虚拟化领域具有其独特的优势&#xff0c;使得它在某些场景下表现尤为出色。以下是几个具体场景&#xff1a; 1. 重载性能需求场景 表现&#xff1a; 高效利用…

聚类分析方法(二)

目录 三、层次聚类方法&#xff08;一&#xff09;层次聚类策略&#xff08;二&#xff09;AGNES算法&#xff08;三&#xff09;DIANA算法 四、密度聚类方法&#xff08;一&#xff09;基本概念&#xff08;二&#xff09;算法描述&#xff08;三&#xff09;计算实例&#xf…

Google账号输入用户名和密码后提醒要到手机通知点是,还要点击数字,但是我手机收不到

有一些朋友换了一个新的电脑后手机登录谷歌账号时&#xff0c;用户名和密码都正确输入以后&#xff0c;第三步弹出一个提示&#xff0c;要在手机上的通知栏点击是&#xff0c;并且点击手机上相应的数字才能继续登录。 但是自己的手机上下拉通知栏却没有来自谷歌的通知&#xf…

ADOQuery 查询MSSQL存储过程一个莫名其妙的错误;

在 SSMS 中执行完成正常的的存储过程。 也能正常的返回想要的数据&#xff0c;&#xff0c;然后通过 ADO 查询时&#xff0c;总是提法 某 字段不存在的问题&#xff1b; 此问题困扰了一天。 例如&#xff08;当然&#xff0c;实际数据结构比下面举例的复杂&#xff09;&…