ClickHouse-查询优化
单表查询【使用的频率高】
1.prewhere代表where
Prewhere 和 where 语句的作用相同,用来过滤数据。不同之处在于 prewhere 只支持*MergeTree 族系列引擎的表,首先会读取指定的列数据,来判断数据过滤,等待数据过滤之后再读取 select 声明的列字段来补全其余属性。
当查询列明显多于筛选列时使用 Prewhere 可十倍提升查询性能,Prewhere 会自动优化执行过滤阶段的数据读取方式,降低 io 操作。
在某些场合下,prewhere 语句比 where 语句处理的数据量更少性能更高
关闭where自动转prewhere
set optimize_move_to_prewhere=0;
使用where的查询:
152 rows in set. Elapsed: 0.691 sec. Processed 8.87 million rows, 3.86 GB (12.83 million rows/s., 5.58 GB/s.)
使用prewhere的查询:
152 rows in set. Elapsed: 0.050 sec. Processed 8.87 million rows, 112.14 MB (176.21 million rows/s., 2.23 GB/s.)
可明显看到使用prewhere扫描的数据更少,耗费的时间更短。
默认情况,我们肯定不会关闭 where 自动优化成 prewhere,但是某些场景即使开启优化,也不会自动转换成 prewhere,需要手动指定 prewhere:
A.使用常量表达式
B.使用默认值为 alias 类型的字段
C.包含了 arrayJOIN,globalIn,globalNotIn 或者 indexHint 的查询
D.select 查询的列字段和 where 的谓词相同
E.使用了主键字段
2. 数据采样
通过采样运算可极大提升数据分析的性能
SELECT
Title,
count(*) AS PageViews
FROM datasets.hits_v1
SAMPLE 1 / 10
WHERE CounterID = 57
GROUP BY Title
ORDER BY PageViews DESC
LIMIT 1000
SAMPLE 0.1 :
代表采样 10%的数据,也可以是具体的条数
采样修饰符只有在 MergeTree engine 表中才有效,且在创建表时需要指定采样策略。
3. 列裁剪与分区裁剪
数据量太大时应避免使用 select * 操作,查询的性能会与查询的字段大小和数量成线性表换,字段越少,消耗的 io 资源越少,性能就会越高。
分区裁剪就是只读取需要的分区,在过滤条件中指定。
4. order by结合where、limit
千万以上数据集进行 order by 查询时需要搭配 where 条件和 limit 语句一起使用。
SELECT
UserID,Age
FROM hits_v1
WHERE CounterID=57
ORDER BY Age DESC LIMIT 1000
5. 避免构建虚拟列
如非必须,不要在结果集上构建虚拟列,虚拟列非常消耗资源浪费性能,可以考虑在前端进行处理,或者在表中构造实际字段进行额外存储。
反例:
SELECT Income,Age,Income/Age as IncRate FROM datasets.hits_v1;
拿到 Income 和 Age 后,考虑在前端进行处理,或者在表中构造实际字段进行额外存储
SELECT Income,Age FROM datasets.hits_v1;
6. uniqCombined替代distinct
性能可提升 10 倍以上,uniqCombined 底层采用类似 HyperLogLog 算法实现,能接收 2%左右的数据误差,可直接使用这种去重方式提升查询性能。Count(distinct )会使用 uniqExact精确去重。
不建议在千万级不同数据上执行 distinct 去重查询,改为近似去重 uniqCombined
SELECT uniqCombined(rand()) from datasets.hits_v1
其他
1)查询熔断
为了避免因个别慢查询引起的服务雪崩的问题,除了可以为单个查询设置超时以外,还可以配置周期熔断,在一个查询周期内,如果用户频繁进行慢查询操作超出规定阈值后将无法继续进行查询操作
2)关闭虚拟内存
物理内存和虚拟内存的数据交换,会导致查询变慢,资源允许的情况下关闭虚拟内存
3)配置join_use_nulls
为每一个账户添加 join_use_nulls 配置,左表中的一条记录在右表中不存在,右表的相应字段会返回该字段相应数据类型的默认值,而不是标准 SQL 中的 Null 值
4)批量写入时先排序
批量写入数据时,必须控制每个批次的数据中涉及到的分区的数量,在写入之前最好对需要导入的数据进行排序。无序的数据或者涉及的分区太多,会导致 ClickHouse 无法及时对新导入的数据进行合并,从而影响查询性能。
5)关注CPU
cpu 一般在 50%左右会出现查询波动,达到 70%会出现大范围的查询超时,cpu 是最关键的指标,要非常关注。
多表关联
1. 用IN代替JOIN
当多表联查时,查询的数据仅从其中一张表出时,可考虑用 IN 操作而不是 JOIN
insert into hits_v2
select a.* from hits_v1 a where a. CounterID in (select CounterID from visits_v1);
2. 大小表join
多表 join 时要满足小表在右的原则,右表关联时被加载到内存中与左表进行比较,ClickHouse 中无论是 Left join 、Right join 还是 Inner join 永远都是拿着右表中的每一条记录到左表中查找该记录是否存在,所以右表必须是小表。
3. 谓词下推
ClickHouse 在 join 查询时不会主动发起谓词下推的操作,需要每个子查询提前完成过滤操作,需要注意的是,是否执行谓词下推,对性能影响差别很大(新版本中已经不存在此问题,但是需要注意谓词的位置的不同依然有性能的差异)
insert into hits_v2
select a.* from hits_v1 a left join visits_v2 b on a. CounterID=b.CounterID
where a.EventDate = '2014-03-17';
耗时:9s
insert into hits_v2
select a.* from (
select * from hits_v1
where EventDate = '2014-03-17'
) a left join visits_v2 b on a. CounterID=b. CounterID;
耗时:7s
4.分布式表使用GLOBAL
两张分布式表上的 IN 和 JOIN 之前必须加上 GLOBAL 关键字,右表只会在接收查询请求的那个节点查询一次,并将其分发到其他节点上。如果不加 GLOBAL 关键字的话,每个节点都会单独发起一次对右表的查询,而右表又是分布式表,就导致右表一共会被查询 N²次(N是该分布式表的分片数量),这就是查询放大,会带来很大开销。
5. 使用字典表
将一些需要关联分析的业务创建成字典表进行 join 操作,前提是字典表不宜太大,因为字典表会常驻内存
6. 提前过滤
通过增加逻辑过滤可以减少数据扫描,达到提高执行速度及降低内存消耗的目的
ClickHouse-查询优化的更多相关文章
- ClickHouse 参数配置
转载自:https://xw.qq.com/cmsid/20200806A0PQ7X00?ADTAG=amp 在 ClickHouse 进程中,CPU 的主频越高越好,通常建议使用 32 以上的机型, ...
- Sentry 监控 - Snuba 数据中台架构简介(Kafka+Clickhouse)
系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...
- 字节跳动基于ClickHouse优化实践之“多表关联查询”
更多技术交流.求职机会.试用福利,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 相信大家都对大名鼎鼎的ClickHouse有一定的了解了,它强大的数据分析性能让人印象深刻.但在字节大量 ...
- 基于 Apache Hudi 极致查询优化的探索实践
摘要:本文主要介绍 Presto 如何更好的利用 Hudi 的数据布局.索引信息来加速点查性能. 本文分享自华为云社区<华为云基于 Apache Hudi 极致查询优化的探索实践!>,作者 ...
- Clickhouse表引擎之MergeTree
1.概述 在Clickhouse中有多种表引擎,不同的表引擎拥有不同的功能,它直接决定了数据如何读写.是否能够并发读写.是否支持索引.数据是否可备份等等.本篇博客笔者将为大家介绍Clickhouse中 ...
- Sentry 后端云原生中间件实践 ClickHouse PaaS ,为 Snuba 事件分析引擎提供动力
目录(脑图) ClickHouse PaaS 云原生多租户平台(Altinity.Cloud) 官网:https://altinity.cloud PaaS 架构概览 设计一个拥有云原生编排能力.支持 ...
- ClickHouse主键索引最佳实践
在本文中,我们将深入研究ClickHouse索引.我们将对此进行详细说明和讨论: ClickHouse的索引与传统的关系数据库有何不同 ClickHouse是怎样构建和使用主键稀疏索引的 ClickH ...
- WebGIS中基于控制点库进行SHP数据坐标转换的一种查询优化策略
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.前言 目前项目中基于控制点库进行SHP数据的坐标转换,流程大致为:遍 ...
- 20170103简单解析MySQL查询优化器工作原理
转自博客http://www.cnblogs.com/hellohell/p/5718238.html 感谢楼主的贡献 查询优化器的任务是发现执行SQL查询的最佳方案.大多数查询优化器,包括MySQL ...
- MySQL索引原理及慢查询优化
原文:http://tech.meituan.com/mysql-index.html 一个慢查询引发的思考 select count(*) from task where status=2 and ...
随机推荐
- vue中使用better-scroll
1.创建vue-cli3项目 指令 vue create 项目名 2.要想使用better-scroll 需要先引入 better-scroll的插件 这里采用 npm的方式 指令 npm ...
- 软件开发工程师,几款常用的APP,你用过几款?最后一个测试网络必备
作为一名程序员,手机里一定有几个常用的app,下面给大家推荐几款. 1. CSDN 国内最大编程论坛:虽然有多少人吐槽现在使用csdn就像屎里淘金, 但是不得不承认他仍然是大家搜索技术资料.问题的首选 ...
- 使用 Nuxt 的 showError 显示全屏错误页面
title: 使用 Nuxt 的 showError 显示全屏错误页面 date: 2024/8/26 updated: 2024/8/26 author: cmdragon excerpt: 摘要: ...
- Shell 目录栈操作
Shell 目录栈允许你将一系列目录压入栈中,然后方便地在这些目录之间进行切换.以下是一些常见的命令及其用途: 常见命令 pushd:将当前目录压入栈中,并切换到指定目录. popd:从栈中移除顶部的 ...
- SSH Agent 的作用
SSH Agent 是一种用于管理 SSH 私钥的程序,它可以帮助用户在使用 SSH 进行认证时,无需每次都手动输入密码.SSH(Secure Shell)是一种加密的网络协议,用于在不安全的网络中安 ...
- web静态和动态的区别
一.静态web页面: 1.在静态Web程序中,客户端使用Web浏览器(IE.FireFox等)经过网络(Network)连接到服务器上,使用HTTP协议发起一个请求(Request),告诉服务器我现在 ...
- 【YashanDB数据库】数据库运行正常,日志出现大量错误metadata changed
问题现象 客户在麒麟kylin v10 sp1环境上部署YashanDB,运行正常, 但是在巡检中发现run.log中有大量错误日志文件metadata changed,需要排查原因 问题单:前置机大 ...
- Openstack-创建实例错误
创建实例错误 实例执行所请求操作失败,实例处于错误状态.: 请稍后再试 [错误: Build of instance beaeb5e0-26eb-4044-ae14-bb87d509886d abor ...
- 技术教程 —— 如何利用 SEI 实现音画同步?
摘要:利用 SEI 解决数据流录制回放过程中的音画不同步问题. 文|即构 Web SDK 开发团队 今年 6 月, ZEGO 即构科技推出了行业内首套数据流录制 PaaS 方案,打破传统录制服务 ...
- CSS – border-radius (Rounded Corners)
前言 之前的文章 CSS – W3Schools 学习笔记 (3), 这篇独立出来写, 作为整理. 参考: Youtube – Advanced CSS Border-Radius Tutorial ...