ClickHouse 进阶【建表、查询优化】

1、ClickHouse 进阶

因为上一节部署了集群模式,所以需要启动 Zookeeper 和 ck 集群;

1.1、Explain 基本语法

EXPLAIN [AST | SYNTAX | PLAN | PIPELINE] [setting = value, ...] 
SELECT ... [FORMAT ...]
  • AST:用于查看语法树
  • SYNTAX:用于优化语法
  • PLAN:用于查看执行计划
    • header:打印计划中各个步骤的 head 说明,默认关闭,默认值 0;
    • description:打印计划中各个步骤的描述,默认开启,默认值 1;
    • actions:打印计划中各个步骤的详细信息,默认关闭,默认值 0;
  • PIPELINE:用于查看 pipeline 计划
    • header:打印计划中各个步骤的 head 说明,默认关闭;
    • graph:用 DOT 图形语言描述管道图,默认关闭,需要查看相关的图形需要配合 graphviz 查看;
    • actions:如果开启了 graph,紧凑打印打,默认开启;

其中,PLAN 和 PIPELINE 还可以进行额外的显示设置;

1.2、建表优化

        在之前使用 Hive 做数仓的时候,我们通常直接把日期类型直接存储为 String 类型,用的时候再用 date_format 函数转一下;但是在 ck 中并不是这样的;

1.2.1、数据类型

1)时间字段类型

        虽然 ClickHouse 底层将 DateTime 存储为时间戳 Long 类型,但不建议把时间存储为 Long 类型, 因为 DateTime 不需要经过函数转换处理,执行效率高、可读性好

CREATE TABLE t_type2
(`id` UInt32,`sku_id` String,`total_amount` Decimal(16, 2),`create_time` DataTime
)
ENGINE = ReplacingMergeTree(create_time)
PARTITION BY create_time
PRIMARY KEY id
ORDER BY (id, sku_id)
2)空值存储类型

        官方已经指出 Nullable 类型几乎总是会拖累性能,因为存储 Nullable 列时需要创建一个额外的文件来存储 NULL 的标记(原因1),并且 Nullable 列无法被索引(原因2)。因此除非极特殊情况,应直接使用字段默认值表示空,或者自行指定一个在业务中无意义的值(例如用-1 表示没有商品 ID)。

        这里指定了列 y 可以为 null (但是这里的 x 不可以为 null,如果非要给 x 列插入 null 的话,默认会被转为 x 列所对应类型的默认值)

可以看到,因为 y 列可以为 null,所以 ck 会为 y 单独创建一个文件存储 null 值;

1.2.2、分区和索引

        分区粒度根据业务特点决定,不宜过粗或过细。一般选择按天分区,也可以指定为 Tuple(), 以单表一亿数据为例,分区大小控制在 10-30 个为最佳。

        必须指定索引列,ClickHouse 中的索引列即排序列,通过 order by 指定,一般在查询条 件中经常被用来充当筛选条件的属性被纳入进来;可以是单一维度,也可以是组合维度的索 引;通常需要满足高级列在前、查询频率大的在前原则;还有基数特别大的不适合做索引列, 如用户表的 userid 字段;通常筛选后的数据满足在百万以内为最佳;

1.2.3、Index_granularity

        Index_granularity 是用来控制索引粒度的,默认是 8192,如非必须不建议调整。

        如果表中不是必须保留全量历史数据,建议指定 TTL(生存时间值),可以免去手动过期 历史数据的麻烦,TTL 也可以通过 alter table 语句随时修改。

 1.2.4、写入和删除优化

  • 尽量不要执行单条或小批量删除和插入操作,这样会产生小分区文件,给后台 Merge 任务带来巨大压力
  • 不要一次写入太多分区,或数据写入太快,数据写入太快会导致 Merge 速度跟不 上而报错,一般建议每秒钟发起 2-3 次写入操作,每次操作写入 2w~5w 条数据(依服务器性能而定)

        在服务器内存充裕的情况下增加内存配额,一般通过 max_memory_usage 来实现

        在服务器内存不充裕的情况下,建议将超出部分内容分配到系统硬盘上,但会降低执行 速度,一般通过 max_bytes_before_external_group_by、max_bytes_before_external_sort 参数 来实现。

1.3、语法优化规则

1.3.1、count 优化

在调用 count 函数时,如果使用的是 count() 或者 count(*),且没有 where 条件,则 会直接使用 system.tables 的 total_rows

查看 count 的执行计划:

注意 Optimized trivial count ,这是对 count 的优化。 如果 count 具体的列字段,则不会使用此项优化:

1.3.2、谓词下推

        当 group by 有 having 子句,但是没有 with cube、with rollup 或者 with totals 修饰的时 候,having 过滤会下推到 where 提前过滤。例如下面的查询,HAVING name 变成了 WHERE name,在 group by 之前过滤:

子查询支持谓词下推:

1.3.3、聚合计算外推

聚合函数内的计算,会外推,例如:

1.4、查询优化

1.4.1、单表查询

1)Prewhere 替代 where

        Prewhere 和 where 语句的作用相同,用来过滤数据。不同之处在于 prewhere 只支持 * MergeTree 族系列引擎的表,首先会读取指定的列数据,来判断数据过滤,等待数据过滤 之后再读取 select 声明的列字段来补全其余属性。

        当查询列明显多于筛选列时使用 Prewhere 可十倍提升查询性能,Prewhere 会自动优化执行过滤阶段的数据读取方式,降低 io 操作。

        在某些场合下,prewhere 语句比 where 语句处理的数据量更少性能更高。

某些场景即使开启优化,也不会自动转换成 prewhere,需要手动指定 prewhere:

  • 使用常量表达式
  • 包含 arrayJOIN,globalIn,globalNotIn 或者 indexHint 的查询
  • select 查询的列字段和 where 的谓词相同
  • 使用了主键字段
1.4.2、数据采样

通过采样运算可极大提升数据分析的性能

SELECTTitle,count(*) AS PageViews
FROM hits_v1
SAMPLE 1 / 10
WHERE CounterID = 57
GROUP BY Title
ORDER BY PageViews DESC
LIMIT 1000

1.4.3、列裁剪与分区裁剪

        数据量太大时应避免使用 select * 操作,查询的性能会与查询的字段大小和数量成线性 表换,字段越少,消耗的 io 资源越少,性能就会越高。

1.4.4、orderby 结合 where、limit

        千万以上数据集进行 order by 查询时需要搭配 where 条件和 limit 语句一起使用;

1.4.5、避免构建虚拟列

        如非必须,不要在结果集上构建虚拟列,虚拟列非常消耗资源浪费性能,可以考虑在前端进行处理,或者在表中构造实际字段进行额外存储;

1.4.6、uniqCombined 替代 distinct

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

        不建议在千万级不同数据上执行 distinct 去重查询,改为近似去重 uniqCombined;

1.4.7、物化视图

        区别于普通视图,物化视图会把数据存下来,而普通视图并不保存数据;

1.5、多表关联

1.5.1、大小表 join

        多表 join 时要满足小表在右的原则,右表关联时被加载到内存中与左表进行比较,ClickHouse 中无论是 Left join 、Right join 还是 Inner join 永远都是拿着右表中的每一条记录 到左表中查找该记录是否存在,所以右表必须是小表。

1.5.2、分布式表使用 GLOBAL

        两张分布式表上的 IN 和 JOIN 之前必须加上 GLOBAL 关键字,右表只会在接收查询请求的那个节点查询一次,并将其分发到其他节点上。如果不加 GLOBAL 关键字的话,每个节点都会单独发起一次对右表的查询,而右表又是分布式表,就导致右表一共会被查询 N²次(N 是该分布式表的分片数量),这就是查询放大,会带来很大开销。

1.6、数据一致性

即便对数据一致性支持最好的 Mergetree,也只是保证最终一致性

        我们在使用 ReplacingMergeTree、SummingMergeTree 这类表引擎的时候,会出现短暂 数据不一致的情况。

在某些对一致性非常敏感的场景,通常有以下几种解决方案:

1.6.1、手动 OPTIMIZE

在写入数据后,立刻执行 OPTIMIZE 强制触发新写入分区的合并动作:

OPTIMIZE TABLE test_a FINAL;

但是数据量大时优化可能非常耗时,而且优化时数据对外无法访问,所以并不推荐使用;

1.6.2、通过 Group by 去重

SELECT user_id , argMax(score, create_time) AS score, argMax(deleted, create_time) AS deleted, max(create_time) AS ctime 
FROM test_a 
GROUP BY user_id 
HAVING deleted = 0;

函数说明:

  • argMax(field1,field2):按照 field2 的最大值取 field1 的值。

比如 argMax(score,create_time),当 score 字段有多个时,取 create_time 最大的;

1.7、物化视图

        ClickHouse 的物化视图是一种查询结果的持久化,它确实是给我们带来了查询效率的提 升。用户查起来跟表没有区别,它就是一张表,它也像是一张时刻在预计算的表,创建的过 程它是用了一个特殊引擎,加上后来 as select,就是 create 一个 table as select 的写法。

         “查询结果集”的范围很宽泛,可以是基础表中部分数据的一份简单拷贝,也可以是多 表 join 之后产生的结果或其子集,或者原始数据的聚合指标等等。所以,物化视图不会随着 基础表的变化而变化,所以它也称为快照(snapshot)

1.7.1、物化视图与普通视图的区别

        普通视图不保存数据,保存的仅仅是查询语句,查询的时候还是从原表读取数据,可以 将普通视图理解为是个子查询。物化视图则是把查询的结果根据相应的引擎存入到了磁盘或内存中,对数据重新进行了组织,你可以理解物化视图是完全的一张新表;

到这里我终于理解了为什么实习的时候一张视图创建了 30 分钟,因为存储引擎用的是 StarRocks 物化视图;

1.7.2、优缺点

优点:查询速度快,要是把物化视图这些规则全部写好,它比原数据查询快了很多,总 的行数少了,因为都预计算好了。

缺点:它的本质是一个流式数据的使用场景,是累加式的技术,所以要用历史数据做去 重、去核这样的分析,在物化视图里面是不太好用的。在某些场景的使用也是有限的。而且 如果一张表加了好多物化视图,在写这张表的时候,就会消耗很多机器的资源,比如数据带 宽占满、存储一下子增加了很多。

1.7.3、语法

也是 create 语法,会创建一个隐藏的目标表来保存视图数据。也可以 TO 表名,保存到 一张显式的表。没有加 TO 表名,表名默认就是 .inner.物化视图名

CREATE [MATERIALIZED] VIEW [IF NOT EXISTS] [db.]table_name [TO[db.]name] 
[ENGINE = engine] [POPULATE] AS SELECT ...

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

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

相关文章

橙单后端项目下载编译遇到的问题与解决

今天下载orange-admin项目&#xff0c;不过下载下来运行出现一些问题。 1、涉及到XMLStreamException的几个类都出现下面的错误 The package javax.xml.stream is accessible from more than one module: <unnamed>, java.xml ctrl-shift-t 可以找到这个引入是哪些包里…

成为git砖家(5): 理解 HEAD

文章目录 1. git rev-parse 命令2. 什么是 HEAD2.1 创建分支当并未切换&#xff0c; HEAD 不变2.2 切换分支&#xff0c;HEAD 改变2.3 再次切换分支&#xff0c; HEAD 再次改变 3. detached HEAD4. HEAD 表示分支、表示 detached HEAD 有什么区别&#xff1f;区别相同点 5. HEA…

【SpringCloud】企业认证、分布式事务,分布式锁方案落地-2

目录 高并发缓存三问 - 穿透 缓存穿透 概念 现象举例 解决方案 缓存穿透 - 预热架构 缓存穿透 - 布隆过滤器 布隆过滤器 布隆过滤器基本思想​编辑 了解 高并发缓存三问 - 击穿 缓存击穿 高并发缓存三问 - 雪崩 缓存雪崩 解决方案 总结 为什么要使用数据字典&…

Python网络爬虫:基础与实战!附淘宝抢购源码

Python网络爬虫是一个强大的工具&#xff0c;用于从互联网上自动抓取和提取数据。下面我将为你概述Python网络爬虫的基础知识和一些实战技巧。 Python网络爬虫基础 1. HTTP请求与响应 网络爬虫的核心是发送HTTP请求到目标网站并接收响应。Python中的requests库是处理HTTP请求…

Java NIO (一)

因工作需要我接触到了netty框架&#xff0c;这让我想起之前为夺高薪而在CSDN购买的Netty课程。如今看来&#xff0c;这套课程买的很值。这套课程中关于NIO的讲解&#xff0c;让我对Tomcat产生了浓厚的兴趣&#xff0c;于是我阅读了Tomcat中关于服务端和客户端之间连接部分的源码…

乐尚代驾六订单执行一

加载当前订单 需求 无论是司机端&#xff0c;还是乘客端&#xff0c;遇到页面切换&#xff0c;重新登录小程序等&#xff0c;只要回到首页面&#xff0c;查看当前是否有正在执行订单&#xff0c;如果有跳转到当前订单执行页面 之前这个接口已经开发&#xff0c;为了测试&…

JAVAWeb实战(后端篇)

因为前后端代码内容过多&#xff0c;这篇只写后端的代码&#xff0c;前端的在另一篇写 项目实战一&#xff1a; 1.创建数据库,表等数据 创建数据库 create database schedule_system 创建表&#xff0c;并添加内容 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------…

Node.js版本管理工具之NVM

目录 一、NVM介绍二、NVM的下载安装1、NVM下载2、卸载旧版Node.js3、安装 三、NVM配置及使用1、设置nvm镜像源2、安装Node.js3、卸载Node.js4、使用或切换Node.js版本5、设置全局安装路径和缓存路径 四、常用命令技术交流 博主介绍&#xff1a; 计算机科班人&#xff0c;全栈工…

Win11 操作(四)g502鼠标连接电脑不亮灯无反应

罗技鼠标连接电脑不亮灯无反应 前言 罗技技术&#x1f4a9;中&#x1f4a9;&#xff0c;贴吧技术神中神&#xff01; 最近买了一个g502&#xff0c;结果买回来直接插上电脑连灯都不亮&#xff0c;问了一下客服。客服简单的让我换接口&#xff0c;又是下载ghub之类的&#xf…

Linux 安装 GDB (无Root 权限)

引入 在Linux系统中&#xff0c;如果你需要在集群或者远程操作没有root权限的机子&#xff0c;安装GDB&#xff08;GNU调试器&#xff09;可能会有些限制&#xff0c;因为通常安装新软件或更新系统文件需要管理员权限。下面我们介绍可以在没有root权限的情况下安装GDB&#xf…

ElasticSearch核心之DSL查询语句实战

什么是DSL&#xff1f; Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。 DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。目前常用的框架查询方法什么的底层都是构建DSL语句实现的&#xff0c;所以你必…

openFeign配置okhttp

原来的项目出现了性能问题&#xff0c;老大不知道怎么的&#xff0c;让我改openFeign线程池为okhttp&#xff0c;说原生的不支持线程池性能比较差。 原openFeign配置文章地址 一、pom文件 <dependency><groupId>org.springframework.cloud</groupId><arti…

【短视频矩阵系统源码部署/技术应用开发】

短视频矩阵系统&#xff1a;选择专业服务商指南 该短视频矩阵系统由多个关键模块组成&#xff0c;包括混剪算法、账号管理与发布、消息处理以及数据管理等。为了优化带宽使用&#xff0c;文件导出功能已被独立处理。 此外&#xff0c;系统还集成了后台运营管理功能。 在技术架…

Python设计模式 - 工厂方法模式

定义 工厂方法模式是一种创建型设计模式&#xff0c;它定义一个创建对象的接口&#xff0c;让其子类来处理对象的创建&#xff0c;而不是直接实例化对象。 结构 抽象工厂&#xff08;Factory&#xff09;&#xff1a;声明工厂方法&#xff0c;返回一个产品对象。具体工厂类都…

git等常用工具以及cmake

一、将git中的代码克隆进电脑以及常用工具介绍 1.安装git 首先需要安装git sudo apt install git 注意一定要加--recursive&#xff0c;因为文件中有很多“引用文件“&#xff0c;即第三方文件&#xff08;库&#xff09;&#xff0c;加入该选项会将文件中包含的子模…

区块链技术如何重塑医疗健康行业未来?

区块链在医疗领域的应用日益广泛&#xff0c;主要体现在以下几个方面&#xff1a; 一、医疗数据管理 电子病历管理&#xff1a; 区块链技术可以用于构建去中心化的电子病历系统&#xff0c;确保病历数据的不可篡改性和安全性。患者可以通过区块链平台安全地管理自己的电子病历…

30岁决心转行,AI太香了

今天是一篇老学员的经历分享&#xff0c;此时的王同学在大洋彼岸即将毕业&#xff0c;手握多家北美大厂offer&#xff0c;一片明媚。谁能想到王同学的转码之路竟始于一场裁员&#xff0c;这场访谈拉开了他的回忆。 最近总刷到一些关于转行的话题&#xff0c;很多刚毕业的同学喜…

【OpenCV C++20 学习笔记】图片融合

图片融合 原理实现结果展示完整代码 原理 关于OpenCV的配置和基础用法&#xff0c;请参阅本专栏的其他文章&#xff1a;垚武田的OpenCV合集 这里采用的图片熔合的算法来自Richard Szeliski的书《Computer Vision: Algorithms and Applications》&#xff08;《计算机视觉&#…

极简Springboot+Mybatis-Plus+Vue零基础萌新都看得懂的分页查询(富含前后端项目案例)

目录 springboot配置相关 依赖配置 yaml配置 MySQL创建与使用 &#xff08;可拿软件包项目系统&#xff09; 创建数据库 创建数据表 mybatis-plus相关 Mapper配置 ​编辑 启动类放MapperScan 启动类中配置 添加config配置文件 Springboot编码 实体类 mapperc(Dao…

LINUX -exec函数族

1、功能&#xff1a; *让父子进程来执行不相干的操作 *能够替换进程地址空间的代码.text段 *执行另外的程序&#xff0c;不需要创建额外的的地址空间 *当前程序中调用另外一个应用程序 2、执行目录下的程序&#xff1a; *指定执行目录下的程序 int execl(const char *path,…