ClickHouse进阶(十七):clickhouse优化-写出查询优化

2023-09-18 11:15:49

进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容!

🏡个人主页:含各种IT体系技术,IT贫道_大数据OLAP体系技术栈,Apache Doris,Kerberos安全认证-CSDN博客

📌订阅:拥抱独家专题,你的订阅将点燃我的创作热情!

👍点赞:赞同优秀创作,你的点赞是对我创作最大的认可!

⭐️ 收藏:收藏原创博文,让我们一起打造IT界的荣耀与辉煌!

✏️评论:留下心声墨迹,你的评论将是我努力改进的方向!

 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频


目录

1. 避免小批量数据写入

2. count优化

3. 避免使用select *

4. 避免构建虚拟列

5. 使用uniqCombined代替count(distinct)

6. 使用物化视图

7. Join关联相关

8. 分布式表使用global

9. 避免使用final


1. 避免小批量数据写入

尽量避免单条和小批量插入、删除操作,会产生大量小分区文件,给后台Merge带来压力。

2. count优化

在clickhouse中向查询数据总条数时,使用count() 代替count(列)查询,因为使用count()查询会自动寻找数据目录中的“count.txt”文件读取数据总条目,性能极高。如果使用count(列)相当于扫描全表读取总数据量。

node1 :) explain plan select count() from person_info;

node1 :) explain plan select count(name) from person_info;

3. 避免使用select *

数据量太大时应避免使用select * 查询,这种查询会将表中所有字段都查询出来,IO消耗大,查询字段越少消耗的IO资源就越少,性能就会越高。

4. 避免构建虚拟列

如果非必要尽量避免在查询时构建虚拟列,虚拟列非常消耗资源,造成性能浪费,可以考虑在前端进行处理或者在表中构建实际的列进行额外存储。

#避免使用虚拟列 ,以下count1/count2就是虚拟列

select id,name,count1,count2,count1/count2 as new_col from tbl;

5. 使用uniqCombined代替count(distinct)

使用uniqCombined替代distinct性能可提升10倍以上,uniqCombined 底层采用类似HyperLogLog算法实现,如能接收2%左右的数据误差,可直接使用这种去重方式提升查询性能。

node1 :) select count(distinct WatchID) from datasets.hits_v1;

 

node1 :) select uniqCombined(WatchID) from datasets.hits_v1;

 

6. 使用物化视图

对于一些确定的数据模型,可以将统计指标通过物化视图的方式进行构建,这样可避免数据查询时重复计算的过程,同样在后期也可以构建Projection投影来替代物化视图。

7. Join关联相关

当多表关联查询时,查询的数据仅来源于一张表时,可考虑用IN代替JOIN,速度会更快。

node1 :) select count(distinct a.CounterID) as cnt  from hits_v1 as a  join visits_v1  as b on a.CounterID = b.CounterID

node1 :) select count(distinct CounterID) as cnt from hits_v1 where CounterID in (select  CounterID from visits_v1);

此外,多表关联时,将小表放在右侧,因为右表自动会被加载到内存中与左表进行关联。

8. 分布式表使用global

对分布式表使用join 或者 in时,clickhouse会将当前SQL分发到各个clickhouse节点上执行,例如有如下SQL:

select a.id,a.name,b.score from a join b on a.id = b.id

如果以上a表和b表都是分布式表,clickhouse集群有3个节点,那么上面SQL会分发到clickhouse所有节点执行,b表会在每个节点上收集其他节点对应b表数据并放在内存,这样的话,每个clickhouse节点都会从对应的3台节点上将b表数据进行汇集。

如果使用global关键字,执行如下SQL:

select a.id,a.name,b.score from a global join b on a.id = b.id

这样执行SQL的话,相当于在当前写SQL节点会将查询得到b表所有数据,然后统一分发到其他clickhouse各个节点上,然后每个节点在执行与a表关联。这样使用global就减少了集群之间查询次数。假设b表有N个分片分布在N个clickhouse节点上,不使用global时,每个节点获取b表全量数据需要执行N的平方次查询,使用global时只需要执行N次查询即可。

所以在使用分布式表进行join或者in时,可以优先考虑使用global,使用用法如下:

select a.id,a.name,b.score from a global join b on a.id = b.id

select a.id,a.name from a global  where a.id global in (select id from b)

9. 避免使用final

clickhouse中我们可以使用ReplacintMergeTree来对数据进行去重,这个引擎可以在数据主键相同时根据指定的字段保留一条数据,ReplacingMergeTree只是在一定程度上解决了数据重复问题,由于自动分区合并机制在后台定时执行,所以并不能完全保障数据不重复。我们需要在查询时在最后执行final关键字,final执行会导致后台数据合并,查询时如果有final效率将会极低,我们应当避免使用final查询,那么不使用final我们可以通过自己写SQL方式查询出想要的数据,举例如下:

#创建replacingMergeTree 表t_replacing_mt

create table t_replacing_mt(

id UInt8,

name String,

age UInt8

) engine = ReplacingMergeTree(age)

order by id;



#向表中插入以下数据

insert into t_replacing_mt values (1,'张三',18),(2,'李四',19),(3,'王五',20);

 

#继续向表中插入如下数据

insert into t_replacing_mt values (1,'张三',20),(2,'李四',15);

 

#通过final查询最终结果
node1 :) select * from t_replacing_mt final;

 

下面我们不使用final,通过自己写SQL方式现在查询最终合并数据,操作如下:

#重新删除表t_replacing_mt,重建、并加载如下数据

drop table t_replacing_mt;



create table t_replacing_mt(

id UInt8,

name String,

age UInt8

) engine = ReplacingMergeTree(age)

order by id;



insert into t_replacing_mt values (1,'张三',18),(2,'李四',19),(3,'王五',20);



#继续向表中插入如下数据

insert into t_replacing_mt values (1,'张三',20),(2,'李四',15);



#自己写SQL方式实现查询去重后的数据,这样避免使用final查询,效率提高

SELECT

    id,

    argMax(name, age) AS namex,

    max(age) AS agex

FROM t_replacing_mt

GROUP BY id

 

注意:argMax(arg,val)函数意思是找到val最大值对应的arg值,如果val有多个相同最大值,则遇到的第一条对应的arg值输出。 

我们还可以针对ReplacingMergeTree表加上一个时间字段,通过自己写SQL方式实现数据更新来避免使用CollapsingMergeTree引擎进行数据更新。当有数据更新时,我们插入这条更新的数据,时间对应的是最新时间,查询时找到最大时间对应的数据即可,不必再创建CollapsingMergeTree引擎使用final语句进行更新数据,具体操作类似以上SQL操作。


👨‍💻如需博文中的资料请私信博主。


更多推荐

展会预告 | 图扑邀您共聚 IOTE 国际物联网展·深圳站

参展时间:9月20日-22日图扑展位:9号馆9B35-1参展地址:深圳国际会展中心(宝安新馆)IOTE2023第二十届国际物联网展·深圳站,将于9月20日-22日在深圳国际会展中心(宝安)9、10、11号馆震撼来袭。本届展会以“IoT构建数字经济底座”为主题,将IoT技术引入实体经济领域,促进数字化转型和智能化升级,推

【运维】dockerfile 中的COPY 会覆盖文件夹吗

Dockerfile中的COPY命令会根据指定的源路径将文件或文件夹复制到容器中的目标路径。行为取决于两个因素:源路径和目标路径以及目标路径的类型。源路径是文件,目标路径是文件:如果源路径是文件,目标路径也是文件,则COPY命令会将源文件复制到目标路径,并覆盖目标路径中的任何现有文件。例如:COPY./source-f

中小企业生产信息化系统哪个好用?选亿发制造业管理系统提供商

中小型制造企业虽然规模相对较小,但同样是市场经济的重要组成部分。要在这个竞争环境中脱颖而出,智能化生产管理系统成为中小型制造企业不可或缺的工具。让各部门之间的数据无缝衔接,实现工厂的整体协调性和工作效率的大幅提升。让我们从几个关键方面来看中小型制造工厂如何选择适合的生产管理系统。生产计划管理:中小型工厂通常需要灵活的生

001 linux 导学

前言本文建立在您已经安装好linux环境后,本文会向您介绍Shell的一些常用指令什么是linuxLinux是一种自由和开放源代码的类UNIX操作系统,该操作系统的内核由林纳斯托瓦兹在1991年首次发布,之后,在加上用户空间的应用程序之后,就成为了Linux操作系统,并在全球范围内得到了广泛的使用和支持。Linux具有

新闻软文的写作要点有哪些?媒介盒子告诉你

信息时代,受众获取信息的方式越来越碎片化,他们对信息的敏感度越来越高,这就导致虽然广告的成本高了,但是广告的效果越来越不明显。这个时候可以考虑新闻软文,新闻体软文是软文与新闻的结合体,它能够提升企业的曝光率,为企业的宣传起到积极作用,那接下来媒介盒子就从三大方面告诉大家,新闻软文的写作方式。一、 保证真实性新

VUE之proxy配置实现跨域

什么是跨域要了解跨域,首先得知道浏览器的同源策略。同源策略:是由Netscape提出的一个安全策略,能够阻挡恶意文档,保护本地数据。它能限制一个源的文档或脚本对另一个源的交互,使得其它源的文档或脚本,无法读取或修改当前源。是否同源:当两个url的域名、协议和端口均相同。举例来说:url:http://127.0.0.1

前后端连接-界面跳转,异步

异步需要有一个js中转前后端数据互通流程:建立jsp文件,连接js文件,在js文件中设置传入后端的值与使用方法(get,post),后端执行完代码后将值返回给js,js接收后返回给jsp;界面跳转流程:表单被提交后,根据设置传入后端的值与使用方法(get,post)在对应的servlet中调用对应的方法,并进行逻辑判断

QT 调用USB免驱摄像头

文章目录前言一、界面布局二、QImageEncoderSettings类三、图像的显示总结前言本篇文章来讲解一下如何使用QT调用摄像头,这里我使用的是USB免驱动摄像头,使用不需要按照驱动QT就可以调用到摄像头。一、界面布局这里使用QT设计师进行界面的布局:二、QImageEncoderSettings类QImageE

【Linux网络编程】Socket-TCP实例

该代码利用socket套接字建立Tcp连接,包含服务器和客户端。当服务器和客户端启动时需要把端口号或ip地址以命令行参数的形式传入。服务器启动如果接受到客户端发来的请求连接,accept函数会返回一个打开的socket文件描述符,区别于监听连接的listensock,它用来为客户端提供服务的。因为有线程池的存在,可以立

Linux设备驱动模型之platform设备

Linux设备驱动模型之platform设备上一章节介绍了Linux字符设备驱动,它是比较基础的,让大家理解Linux内核的设备驱动是如何注册、使用的。但在工作中,个人认为完全手写一个字符设备驱动的机会比较少,更多的都是基于前人的代码修修补补过三年。在内核驱动中,你会看到比较多的platform相关的字样,他们具体是什

涨知识,关于代码签名证书10大常见问题解答

在当今互联网+时代,各种软件程序充斥着这个网络世界,大大小小的软件层出不穷,如何让用户信任软件并下载软件,是众多软件开发公司需要解决的问题,由此代码签名证书应运而生,提供了软件程序的身份认证、完整性和可信任性的解决方案。那么什么是代码签名证书?代码签名证书的原理是什么?锐成小编收集整理了关于代码签名证书10大常见问题解

热文推荐