数据分析ClickHouse学习笔记

news2024/11/24 5:23:51

一、ClickHouse基础

1.1 ClickHouse介绍

ClickHouse是一个用于联机分析(OLAP)的列式DBMS。

简单来说,相比MySQL等行式数据库,数据存储方式是:

Rowidis_deltitlesexcreateAt
#021a12024/2/18 5:19
#130b12024/2/18 8:10
#241c12024/2/18 7:38
#N

即是:处于同一行中的数据总是被物理的存储在一起。

在列式数据库系统中,数据按如下的顺序存储:

Row:#0#1#2#N
id234
is_del101
titleabc
sex111
createAt2024/2/18 5:192024/2/18 8:102024/2/18 7:38

即是:来自不同列的值被单独存储,来自同一列的数据被存储在一起。

这种数据存储方式适用不同的业务场景,数据访问的场景包括:

1.进行了何种查询、多久查询一次以及各类查询的比例;

2.每种类型的查询(行、列和字节)读取多少数据;

3.读取数据和更新之间的关系;

4.使用的数据集大小以及如何使用本地的数据集;

5.是否使用事务,以及它们是如何进行隔离的;

6.数据的复制机制与数据的完整性要求;

7.每种类型的查询要求的延迟与吞吐量

做个例子,以下表数据为例:

idnameage
1张三12
2李四13
3王五14

行式存储,数据在磁盘的组织结构:

在这里插入图片描述

列式存储,数据在磁盘的组织结构:

在这里插入图片描述

行式存储应用场景在查询某个人的所有属性,只需根据索引一次磁盘查找加顺序读取即可。但是当列变多,每次只查询一列或者某几列(统计所有人年龄平均值),如果还是行式存储数据,需要全表扫描,遍历很多数据都是不需要的。而列式存储想查询所有人年龄,只需把年龄一列拿出即可

1.2 OLAP和OLTP

OLTP(On-Line Transaction Processing):联机事务处理,典型代表是关系型数据库(如MySQL),它的数据存储在服务器本地的文件里

OLAP(On-Line Analytical Processing):联机分析处理,OLAP型数据库的典型代表是分布式文件系统(hive),它的数据存储在HDFS集群里

OLTPOLAP
业务目的处理业务,如订单,进销存业务支持决策
面向对象业务处理人分析决策人
主要工作负载增删改查询
主要衡量指标事务吞吐量查询响应速度(QPS)
数据库设计3NF/BCNF星型/雪花模型
1.3 OLAP场景的关键特征
  • 绝大多数是读请求
  • 数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
  • 已添加到数据库的数据不能修改。
  • 对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
  • 宽表,即每个表包含着大量的列
  • 查询相对较少(通常每台服务器每秒查询数百次或更少)
  • 对于简单查询,允许延迟大约50毫秒
  • 列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
  • 处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
  • 事务不是必须的
  • 对数据一致性要求低
  • 每个查询有一个大表。除了他以外,其他的都很小。
  • 查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中

可以看出,OLAP场景与其他通常业务场景(例如,OLTP或K/V)有很大的不同, 因此想要使用OLTP或Key-Value数据库去高效的处理分析查询场景,并不是非常完美的适用方案。

1.4 列式数据库更适合OLAP场景的原因
输入/输出
  1. 针对分析类查询,通常只需要读取表的一小部分列。在列式数据库中你可以只读取你需要的数据。例如,如果只需要读取100列中的5列,这将帮助你最少减少20倍的I/O消耗。
  2. 由于数据总是打包成批量读取的,所以压缩是非常容易的。同时数据按列分别存储这也更容易压缩。这进一步降低了I/O的体积。
  3. 由于I/O的降低,可以让更多的数据被系统缓存。

例如,查询«统计每个广告平台的记录数量»需要读取«广告平台ID»这一列,它在未压缩的情况下需要1个字节进行存储。如果大部分流量不是来自广告平台,那么这一列至少可以以十倍的压缩率被压缩。当采用快速压缩算法,它的解压速度最少在十亿字节(未压缩数据)每秒。换句话说,这个查询可以在单个服务器上以每秒大约几十亿行的速度进行处理。这实际上是当前实现的速度。

CPU

由于执行一个查询需要处理大量的行,因此在整个向量上执行所有操作将比在每一行上执行所有操作更加高效,减少调用成本的查询引擎。

数据压缩

能存储大量数据的数据库都是采用列式存储的,它压缩比极高,如果压缩比低,是无法存储海量数据的,数据库的存储格式决定了存储的体积。

行式存储每一行的数据格式不同,有数字,文本,日期型等,很大的问题就是,不同的格式无法采用统一的压缩格式,而列式存储一列是一个数据块,是同一个数据格式,很好的弥补了压缩比低的缺点。

压缩比高好处是同样规模的数据,占用的空间小,可以节省磁盘,更重要的是可以节省内存,对于内存小的可以将更多的数据放到其中,如对于128G内存能够管理的列式存储的数据远远大于行式存储的数据,这样管理行式存储的数据需要分布式,代理中间件等,十分复杂,列式存储可能一台机器就足够了,节省资源。

列式储存的好处:

1.对于列的聚合,计数,求和等统计操作原因优于行式存储,只需要遍历一个数据块,而行式存储则需要遍历所有的数据块。
由于某一列的数据类型都是相同的,针对于数据存储更容易进行数据压缩,每一列选择更优的数据压缩算法,大大提高了数据的压缩比重。
2.由于数据压缩比更好,一方面节省了磁盘空间,另一方面对于cache也有了更大的发挥空间。

列式存储的劣势:

1.不支持事务。
2.对行级别的查询不方便,列式存储一般负责范围的查询。

1.5 读与写
写(MergeTree)

ClickHouse采用类LSM Tree的结构(HBase也使用的这种结构),数据写入后定期在后台合并。通过类LSM tree的结构,但没有内存表,没有预写日志,ClickHouse在数据导入时全部是顺序append写入磁盘,在后台周期性合并数据到主数据段。顺序写的特性,充分利用了磁盘的吞吐能力,即便在HDD上也有着优异的写入性能。

尤其是当在批量插入的场景下,MySQL是真正的将数据一条一条的写入到数据库中,磁盘一致地在移动,而ClickHouse会将大量的数据直接放到临时分区中,然后ClickHouse会自动调用进程去后台处理,compaction 时也是多个段 merge sort 后顺序写回磁盘。

读(MergeTree)

(1)稀疏索引
索引:用于查询,通过索引可以查找到数据的具体位置,关系型数据库中默认没有索引,但一般来说每张表都需要加一个主键,主键就是索引,在hive中,分区也相当于一个索引,这两种索引的不同在于粒度。

MySQL一般使用稠密索引,即尽可能的让每一条数据都有一个索引,对应公交车的站牌,可以精确定位到一个地点。

clickhouse使用稀疏索引,索引之间的颗粒度(默认8192行),对应火车站的车站,可以定位到一个范围,想找到具体的数据,还需要在这个范围内进行逐表扫描。

在这里插入图片描述

稀疏索引的好处是可以用很少的索引数据,定位更多的数据,范围查询过滤比较快,代价是只能定位到索引粒度第一行,然后再逐个扫描数据,不适合做点对点查询。对于稠密和稀疏两种设计思路没有好坏,只有取舍,而语句级多线程就是针对稀疏索引的缺点做的一些优化。

(2)语句级多线程
MySQL是多线程,但不是语句级的,其处理任意一条SQL,只使用一个线程,MySQL可以执行多条SQL,所以多线程这个功能也不会浪费,对多条SQL开多个线程,不同SQL之间互相独立。

ClickHouse不同,它会针对一条SQL启动多个线程共同完成,如上图中,会在10101 - 22222,32343 - 76543,76766 - 98345会启动三个线程同时进行查询,在ClickHouse中每一个间隔都称为颗粒,默认为8192行,即一个线程最多扫描8192行。

ClickHouse将数据划分为多个partition,每个partition再进一步划分为多个index granularity(索引颗粒),然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。

在这种设计下,单条Query就能利用整机所有CPU。极致的并行处理能力,极大的降低了查询延时。

MySQL一般接受简单、数据量小的查询(业务系统),导致QPS相对较高,每个查询的资源较少,只有一个线程对一个查询,但是可以支持更多查询。

ClickHouse适合复杂数据量大的查询(分析系统),QPS不高,每个查询投入的资源更多,多个线程对一个查询,但是支持的查询更少。

弊端:clickhouse即使对于大量数据的查询也能够化整为零平行处理。但是有一个弊端就是对于单条查询使用多cpu,就不利于同时并发多条查询。所以对于高qps的查询业务,clickhouse并不是强项。

1.6多样化引擎

ClickHouse 和 MySQL 类似,把表级的存储引擎插件化,根据表的不同需求可以设定不同
的存储引擎。目前包括合并树、日志、接口和其他类这四大类 20 多种引擎。

Clickhouse 中最强大的表引擎是 MergeTree (合并树)引擎及该系列(MergeTree)中的其他引擎。 MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不断修改(重写)已存储的数据,这种策略会高效很多。

合并树系列:MergeTree、ReplacingMergeTree(分区内主键去重)、CollapsingMergeTree(标记列 Sign)、VersionedCollapsingMergeTree(快速写入不断变化的对象状态)、SummingMergeTree(对主键列进行预先聚合)、AggregatingMergeTree(高级预先聚合)

对于MergeTree的一些理解:

1.存储的数据按主键排序。 这使得能够创建一个小型的稀疏索引来加快数据检索。
2.如果指定分区键的话,可以使用分区。在相同数据集和相同结果集的情况下ClickHouse中某些带分区的操作会比普通操  作更快。查询中指定分区键时ClickHouse会自动截取分区数据,有效增加查询性能。
3.支持数据副本。 ReplicatedMergeTree系列的表提供了数据副本功能
4.支持数据采样。需要时可以给表设置一个采样方法。

–MergeTree建表语句

CREATE TABLE [IF NOT EXISTS] [db_name.]table_name (
name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
name2 [type] [DEFAUErEMAMLERLALLIZED|ALIAS expr],
省略...
) ENGINE = MergeTree()
[PARTITION BY expr]
[ORDER BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name=value, 省略...]

order by 设定分区内的数据按照哪些字段顺序进行有序保存。 order by 是 MergeTree 中唯一一个必填项,甚至比 primary key 还重要,因为当不设置主键的情况,很多处理会依照 order by 的字段进行处理(比如去重和汇总)。 要求:主键必须是 order by 字段的前缀字段。 比如: order by 字段是 (id, u_id) ,那主键必须是 id 或者(id, u_id)

1.7 基于ClickHouse构建标签画像示例

1.标签表结构演进

表结构:

tag_iduser_id
tagnum1101
tagnum1102
tagnum2101
tagnum3101
#####DDL
CREATE TABLE ......ORDER BY (tag_id,user_id)
engine=MergeTree()

###用户圈选,交集
SELECT user_id FROM xxx WHERE tag_id=1 AND
user_id IN (select user_id from xxx
where tag_id =2
)
where tagID= 1

###用户画像,基于人群进行画像分析
SELECT tag_id ,count(1) FROM xxx AND
uid IN (select user_id from xxx
where tag_id =2
)and tag_id in (4,5,6,7)
GROUP BY tag_id

​ 优势:

  • 表结构简单,标签扩展简单

  • 同一个uid 数据只在shard,增加并行查询效率

    劣势:

  • 标签和用户量增加,数据行数膨胀迅速,查询效率衰减明显

  • 多条件嵌套查询SQL 复杂

2.标签表结构演进

user_idtag1tag2tagN
101F1020
101M2030
102M1030
#####DDL:
CREATE TABLE( ......
user_id UInt64,
tag1 SimpleAggregateFunction(anyLast, Nullable(Enum(‘女’ = F, '男’ = M)
.........
)
ORDER BY uid ENGINE= AggregatingMergeTree()

###用户圈选,交集
SELECT uid FROM table_users WHERE anyLastMerge(tag1)=‘F ’ AND
anyLast(tag2)= 10

### 用户标签详情
SELECT uid FROM table_users WHERE anyLastMerge(tagID)=‘F ’
AND anylastMerge(tag2)= 10

###用户画像,基于已有人群进行用户画像分析
SELECT tag1 ,count(1) FROM table_users AND
user_id IN (select user from xxx
where tag2 =10
)GROUP BY tag

优缺点:

  • 数据行数减少,SQL 语句简单
  • SimpleAggregateFunction (anylast,…)支持标签值更新
  • 交,并,差,SQL表达复杂(在线分析效率低)

3.标签表结构演进

tagtag_valueuser_ids(bitmap)
tag1F(101,102,103,)
tag1M(104,105,)
tag320(101,)

在这里插入图片描述

数据存储与同步

###离线任务计算标签结果:
create table label_local(
tag String ,
tag_value String ,
user_id UInt64
)
ENGINE = MerTree()
partition by tag
order by tag,tag_value

### bitmap标签表
create table label_bitmap_local
(
tag String comment '标签名称',
tag_value String comment '标签值',
user_ids AggregatingMergeTree()
)
partition by tag
order by (tag,tag_value)
settings index_granularity = 128;

###数据导入
insert into table  label_bitmap_local
select 
tag,
tag_value,
groupBitmapState(user_id)
from label_local
group by tag,tag_value

使用bitmap做人群(群体)圈选

with
(
    select  groupbitmapMergeState(user_ids)  //获取满足条件数据包
    from label_bitmap_local
    where tag='性别' and tag_value = '女'
)as user_group_1,
(
    select  groupbitmapMergeState(user_ids) 
    from label_bitmap_local
    where tag='年龄段' and tag_value = '18-30'
) as user_group_2 
select  bitmapToArray(bitmapAnd(user_group_1,user_group_2)) //求交集,转数组
### Result = (性别=女生) ∩(年龄段=18-30)= 年轻女性

群体分析

###人群预估,群体基数
select bitmapCardinality(bitmapAnd(user_group_1,user_group_2)) 

###查询个人是否存在群体中
select bitmapContains(bitmapAnd(user_group_1,user_group_2),user_id)

### 查询群体是否存在公共元素
select bitmapHasAny(user_group_1,user_group_2) 

### 群体是否包含另一群体所有
select bitmapHasAll(user_group_1,user_group_2)

###圈定群体(年轻女性)其他情况分布(消费水平)
with
(
select bitmapAnd(user_group_1,user_group_2) 
) as filter_users

select  bitmapCardinality(bitmapAnd(filter_users, group_by_users)) AS count,    
tag,  
tag_value 
from (
        SELECT    groupBitmapMergeState(user_ids) AS group_by_users,    tag,    tag_value
        FROM lable_bitmap_local
        WHERE tag = "消费水平"
        GROUP BY (tag, tag_value)
        );
  //年轻女性群体消费能力分布
1.8 缺点、局限

不支持事务,不支持真正的删除/更新;

数据一致性差,或者只能保证最终数据一致性

适用宽边多维度分析查询,多表join性能差 可以使用物化视图进行优化

不支持高并发,官方建议qps为100 Clickhouse快是由于采用了并行处理机制,即便一个查询,也会用服务器一半的CPU去执行,因此ClickHouse不能支持高并发的使用场景,默认单查询使用CPU核数为服务器核数的一半

1.9优化

1.建议每次写入多于1000行的批量写入,或每秒不超过一个写入请求

2.同一个分区的 两个part的数据量都很大,然后后台自动的merge合并成一个的时候,会消耗大量的cpu 控制merge的线程,后台默认的线程数是16 降低线程数的配置; 实时的数据尽量在ssd上.

3.选择更加合适的引擎

4.建表优化:尽量不使用 Nullable 类型,避免数据出现大量空值字段,空值会被单独存储,字段可以设置默认值;

5.分区粒度:分区粒度根据业务场景特性来设置,不宜过粗也不宜过细。我们的数据一般都是按照时间来严格划分,所以都是按天、按月来划分分区。如果索引粒度过细按分钟、按小时等划分会产生大量的分区目录,更不能直接 PARTITION BY create_time ,会导致分区数量惊人的多,几乎每条数据都有一个分区会严重的影响性能。

1.9.1慢查询优化

ClickHouse 在 20.6 版本后已经提供查看查询计划的原生 EXPLAIN,但是提供的信息对慢 SQL 优化提供的帮助不是很大,推荐使用查看服务日志这种方式进行分析,这种方式需要使用 clickhouse-client 进行执行 SQL 语句。

举个栗子,通过query_log_all 定位到一个慢 SQL:

select ifNull(sum(price), 0) as total_price
from wms.wms_order_sku_local final    
prewhere tranTime = '2024-02-27 08:00:00' and orderType = '10'
where is_del = '0'  and is_valid = '0'

使用 clickhouse-client,send_logs_level 参数指定日志级别为 trace。

clickhouse-client -h 地址 --port 端口 --user 用户名 --password 密码 --send_logs_level=trace

在 client 中执行上述慢 SQL,服务端打印核心日志如下:

 1.(SelectExecutor): Key condition: unknown              没有使用主键索引:导致全表扫描
 
 2.(SelectExecutor): MinMax index condition: unknown     没有使用分区索引:导致全表扫描
 
 3.MemoryTracker: Peak memory usage (for query): 60.37 MiB.   查询语句消耗的内存最大为 60.37MB
 
 4.(SelectExecutor): Selected 36 parts by date, 9390 marks by primary key   共扫描 36 个 parts,9390 个 MarkRange,查询system.parts系统分区信息表发现当前表共拥有36个活跃分区,相当于全表扫描。

所以需要再查询条件上添加主键字段或者分区索引来进行优化。比如将tranTime为分区键,在添加这个条件后可以看到没有使用主键索引,但使用分区索引,扫描分片数为 6,MarkRange 186,共扫描 1409001 行数据,使用内存 40.76MB,扫描数据大小等大幅度降低节省大量服务器资源,并且提升了查询速度,0.267s 降低到 0.18s。

1.9.2条件聚合函数降低扫描数据行数

假设要统计某天的” 入库件量”,” 有效出库单量”,” 复核件量”三个指标。

-- 入库件量:select sum(qty) from table_1 final prewhere type = 'inbound' and dt = '2024-01-01';
-- 有效出库单量:select count(distinct orderNo) final from table_1 prewhere type = 'outbound' and dt = '2024-01-01' where and status = '1' ;
-- 复核件量:select sum(qty) from table_1 final prewhere type = 'check' and dt = '2024-01-01';

查询三个指标需要上述三个 SQL 语句查询 table_1 来完成,但dt 是一致的,区别在于 type 和 status 两个条件。假设 dt = ‘2024-01-1’ 每次查询需要扫描 100W 行数据,那么一次接口请求将会扫描 300W 行数据。通过条件聚合函数优化后将三次查询改成一次,那扫描行数将降低为 100W 行,可极大的节省集群计算资源。

select sumIf(qty, type = 'inbound'), 
-- 入库件量countIf(distinct orderNo, type = 'outbound' and status = '1'),
-- 有效出库单量sumIf(qty, type = 'check') 
-- 复核件量prewhere dt = '2024-01-01';

条件聚合函数比较灵活,可根据业务情况自由发挥,核心是减少整体的扫描量,来提升查询性能。

1.9.3二级索引

MergeTree 系列的表引擎可以指定跳数索引。
跳数索引是指数据片段按照粒度 (建表时指定的 index_granularity) 分割成小块后,将 granularity_value 数量的小块组合成一个大的块,对这些大块写入索引信息,这样有助于使用 where 筛选时跳过大量不必要的数据,减少 SELECT 需要读取的数据量。

CREATE TABLE table_name(u64 UInt64,
i32 Int32,    
s String,    ...    
INDEX a (u64 * i32, s) 
TYPE minmax GRANULARITY 3,    
INDEX b (u64 * length(s)) 
TYPE set(1000) GRANULARITY 4) ENGINE = MergeTree()...

上例中的索引能让 ClickHouse 执行下面这些查询时减少读取数据量。

SELECT count() FROM table WHERE s < 'z' SELECT count() FROM table WHERE u64 * i32 == 10 AND u64 * length(s) >= 1234

支持的索引类型:

1.minmax:以 index granularity 为单位,存储指定表达式计算后的 min、max 值;在等值和范围查询中能够帮助快速跳过不满足要求的块,减少 IO。

2.set (max_rows):以 index granularity 为单位,存储指定表达式的 distinct value 集合,用于快速判断等值查询是否命中该块,减少 IO。

3.ngrambf_v1 (n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed):将 string 进行 ngram 分词后,构建 bloom filter,能够优化等值、like、in 等查询条件。

4.tokenbf_v1 (size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed): 与 ngrambf_v1 类似,区别是不使用 ngram 进行分词,而是通过标点符号进行词语分割。

5.bloom_filter ([false_positive]):对指定列构建 bloom filter,用于加速等值、like、in 等查询条件的执行。

创建二级索引:

Alter table wms.wms_order_sku_local 
ON cluster default 
ADD INDEX belongProvinceCode_idx belongProvinceCode 
TYPE set(0) GRANULARITY 5;

Alter table wms.wms_order_sku_local 
ON cluster default 
ADD INDEX productionEndTime_idx productionEndTime 
TYPE minmax GRANULARITY 5;

重建分区索引数据:在创建二级索引前插入的数据,不能走二级索引,需要重建每个分区的索引数据后才能生效

-- 拼接出所有数据分区的MATERIALIZE语句
select concat('alter table wms.wms_order_sku_local on cluster default ', 'MATERIALIZE INDEX productionEndTime_idx in PARTITION '||partition_id||',')from system.partswhere database = 'wms' and table = 'wms_order_sku_local'group by partition_id
-- 执行上述SQL查询出的所有MATERIALIZE语句进行重建分区索引数据
1.9.4final 替换 argMax 进行去重

对比下 final 和 argMax 两种方式的性能差距,如下 SQL

-- final方式:
select count(distinct groupOrderCode), sum(arriveNum), count(distinct sku) from tms.group_order final prewhere siteCode = 'WG0001544' and createTime >= '2024-02-24 22:00:00' and createTime <= '2024-02-27 22:00:00' where arriveNum > 0 and test <> '1'

-- argMax方式:
select count(distinct groupOrderCode), sum(arriveNumTemp), count(distinct sku) from (select argMax(groupOrderCode,version) as groupOrderCode, argMax(arriveNum,version) as arriveNumTemp, argMax(sku,version) as sku from tms.group_order prewhere siteCode = 'WG0001544' and createTime >= '2024-02-24 22:00:00' and createTime <= '2024-02-27 22:00:00' where arriveNum > 0 and test <> '1' group by docId)

在这里插入图片描述

final 方式的 TP99 明显要比 argMax 方式优秀很多

1.9.5prewhere 替代 where

ClickHouse 的语法支持额外的 prewhere 过滤条件,它会先于 where 条件进行判断,可以看做是更高效率的 where,作用都是过滤数据。当在 sql 的 filter 条件中加上 prewhere 过滤条件时,存储扫描会分两阶段进行,先读取 prewhere 表达式中依赖的列值存储块,检查是否有记录满足条件,再把满足条件的其他列读出来。以下述的 SQL 为例,其中 prewhere 方式会优先扫描 type,dt 字段,将符合条件的列取出来,当没有任何记录满足条件时,其他列的数据就可以跳过不读了。相当于在 Mark Range的基础上进一步缩小扫描范围。prewhere 相比 where 而言,处理的数据量会更少,性能会更高。

-- 常规方式:
select count(distinct orderNo) final from table_1 where type = 'outbound' and status = '1' and dt = '2024-01-01';

-- prewhere方式:
select count(distinct orderNo) final from table_1 prewhere type = 'outbound' and dt = '2024-01-01' where and status = '1' ;

PS小坑:prewhere 会优先于 final 进行执行,所以对于 status 这种值可变的字段处理过程中,能够查询到中间状态的数据行,导致最终数据不一致。

idversionstatusorderNotypedt
11101311outbound2024-01-01
11211311outbound2024-01-01
11321311outbound2024-01-01

如表所示,id:1 的业务数据,进行三次写入,到 version=13 的数据是最新版本数据,当我们使用 where 过滤 status 这个可变值字段时,语句 1,语句 2 结果如下。

--语句1:使用where + status=1 查询,无法命中id:1这行数据,select count(distinct orderNo) final from table_1 where type = 'outbound' and dt = '2024-01-01' and status = '1';

--语句2:使用where + status=2 查询,可以查询到id:1这行数据,select count(distinct orderNo) final from table_1 where type = 'outbound' and dt = '2024-01-01' and status = '2';

当我们prewhere 后,语句 3 写法:prewhere 过滤 status 字段时将 status=1,version=12 的数据会过滤出来,导致我们查询结果不正确。正确的写法是将不可变字段使用 prewhere 进行优化。

-- 语句3:错误方式,将status放到prewhere
select count(distinct orderNo) final from table_1 prewhere type = 'outbound' and dt = '2024-01-01' and status = '1';

-- 语句4:正确prewhere方式,status可变字段放到where上
select count(distinct orderNo) final from table_1 prewhere type = 'outbound' and dt = '2024-01-01' where and status = '1' ;

其他限制:prewhere 目前只能用于 MergeTree 系列的表引擎

1.9.6 where、group by 顺序

where 和 group by 中的列顺序,要和建表语句中 order by 的列顺序统一,并且放在最前面使得它们有连续不间断的公共前缀,否则会影响查询性能。

-- 建表语句create table group_order_local(    docId              String,    version            UInt64,    siteCode           String,    groupOrderCode     String,    sku                String,    ... 省略非关键字段 ...     createTime         DateTime) engine = ReplicatedReplacingMergeTree('/clickhouse/tms/group_order/{shard}', '{replica}', version)PARTITION BY toYYYYMM(createTime)ORDER BY (siteCode, groupOrderCode, sku);

--查询语句1:
select count(distinct groupOrderCode) groupOrderQty, ifNull(sum(arriveNum),0) arriveNumSum,count(distinct sku) skuQty from tms.group_order final prewhere createTime >= '2024-01-01 22:00:00' and createTime <= '2024-02-01 22:00:00'and siteCode = 'WG0000709'where arriveNum > 0 and test <> '1'

--查询语句2 (where/prewhere中字段):
select count(distinct groupOrderCode) groupOrderQty, ifNull(sum(arriveNum),0) arriveNumSum,count(distinct sku) skuQty from tms.group_order final prewhere siteCode = 'WG0000709' and createTime >= '2024-01-01 22:00:00' and createTime <= '2024-02-01 22:00:00'where arriveNum > 0 and test <> '1'

建表语句 ORDER BY (siteCode, groupOrderCode, sku),语句 1 没有符合要求经过压测 QPS6.4,TP99 0.56s,语句 2 符合要求经过压测 QPS 14.9,TP99 0.12s

在这里插入图片描述

1.9.7性能测试

clickhouse 提供的一个 clickhouse-benchmark 性能测试工具,可通过 docker 搭建 CK 环境。

clickhouse-benchmark -c 1 -h 链接地址 --port 端口号 --user 账号 --password 密码 <<< "具体SQL"

通过这种方式可以了解 SQL 级别的 QPS 和 TP99等信息,这样就可以测试语句优化前后的性能差异。

1.10 保证高并发 ClickHouse 可用性

1)降低查询速度,提高吞吐量

max_threads:位于 users.xml 中,表示单个查询所能使用的最大 CPU 个数,默认是 CPU 核数,假如机器是 32C,则会起 32 个线程来处理当前请求。可以把 max_threads 调低,牺牲单次查询速度来保证 ClickHouse 的可用性,提升并发能力。可通过 jdbc 的 url 来配置

在这里插入图片描述

max_threads 做的一个压测,接口级别压测,一次请求执行 5 次 SQL,处理数据量 508W 行。可以看出 max_threads 越小,QPS 越优秀 TP99 越差。可根据自身业务情况来进行调整一个合适的配置值。

在这里插入图片描述

2)接口增加一定时间的缓存
3)异步任务执行查询语句,将聚合指标结果落到 ES 中,应用查询 ES 中的聚合结果
4)物化视图,通过预聚合方式解决这种问题,但是我们这种业务场景不适用

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

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

相关文章

车载测试工程师在行业中有哪些挑战需要面对?

车载测试工程师在行业中面临着多方面的挑战&#xff0c;这些挑战涵盖了技术、安全、法规以及市场环境等多个层面。 1. 技术挑战&#xff1a; 复杂性与集成性&#xff1a;现代汽车系统由众多模块和子系统组成&#xff0c;包括发动机控制、安全系统、娱乐系统、导航系统等。这些系…

新品Coming Soon!OAK-D-SR-PoE:使用3D+AI视觉结合ToF实现箱体测量和鉴别!

OAKChina 新品&#xff1a;OAK-D SR PoE结合ToF实现箱体检测 3DAI解决方案提供商 手动测量箱体、缺陷、大小等操作可能是一项繁琐并且劳累而机械的任务&#xff0c;但OAK中国本次将提供了更好的解决方案&#xff1a;3DAI视觉处理箱体的识别和检测&#xff0c;使用了即将发布的…

KVM性能优化之网络性能优化

1、使用virtio半虚拟化网卡 在Virt- Manager图形界面里指定下&#xff1a; 当然也可以编辑XML文件&#xff0c;添加<model typevirtio/> 如果你不指定&#xff0c;那么虚拟机会默认使用8139的全虚拟化网卡&#xff0c;8139网卡是Realtek的百兆。 2、使用vhost_net v…

Windows和Linux C++判断磁盘空间是否充足

基本是由百度Ai写代码生成的&#xff0c;记录一下。实现此功能需要调用系统的API函数。 对于Windows&#xff0c;可调用函数GetDiskFreeSpaceEx&#xff0c;使用该函数需要包含头文件windows.h。该函数的原型&#xff1a; 它的四个参数&#xff1a; lpDirectoryName&#xff0…

Gitlab上传代码时自动触发Jenkins构建代码配置

Jenkins配置构建触发器&#xff0c;勾选Build when a change is pushed to GitLab 记得记住对应url 在下面生成一个Jenkins的Secret token 打开Gitlab配置Webhooks 保存后测试 可正常构建并推送

DIY:在您的 PC 上本地使用 Stable Diffusion AI 模型生成图像

前言 随着DALL-E-2和Midjourney的发布&#xff0c;您可能听说过最近 AI 生成艺术的繁荣。这些人工智能模型如何在几秒钟内创造性地生成逼真的图像&#xff0c;这绝对是令人兴奋的。您可以在这里查看其中的一些&#xff1a;DALL-E-2 gallery和Midjourney gallery 但是这些模型…

Linux-引导过程与服务控制

目录 一、Linux操作系统引导过程 1、引导过程总览 2、引导过程详解 2.1、开机自检&#xff08;BIOS&#xff09; 2.2、 MBR引导 2.3、GRUB菜单 2.4、加载内核(kernel) 2.5、init进程初始化 3、系统初始化进程 3.1、Systemd单元类型 3.2、运行级别所对应的 Systemd 目…

湖北大学2024年成人高考函授报名专升本汉语言文学专业介绍

湖北大学&#xff0c;这所历史底蕴深厚的学府&#xff0c;自创办以来&#xff0c;始终致力于为社会各界人士提供高质量的成人高等继续教育。而今&#xff0c;为了满足广大成年人对于知识更新的渴求&#xff0c;学校特别开放了专升本汉语言文学专业的报名通道&#xff0c;为那些…

揭开免费可视化工具流行背后的原因

免费可视化工具为什么越来越受欢迎&#xff1f;在大数据时代&#xff0c;数据可视化已经成为各行各业的重要工具。它不仅帮助企业和个人更直观地理解数据&#xff0c;还在决策过程中起到关键作用。尽管市场上有许多付费的数据可视化工具&#xff0c;但免费工具的受欢迎程度却在…

rtthread 设备驱动 示例

添加自定义驱动效果 驱动 my_test_driver.c #include <stdint.h> #include <stdio.h> #include <rtthread.h> /*** brief 驱动初始化设备* * param device 需要初始化的设备* return rt_err_t 返回初始化状态*/ rt_err_t my_test_driver_init(struct rt_de…

RAID在VPS主机中的作用是什么?

您是否担心过网站的可靠性&#xff1f;有时候网站会崩溃。服务器会不稳定。 在高峰时段&#xff0c;即使最好的网站也会变得很慢&#xff0c;让人很烦。 这就是VPS主机发挥作用的地方——为您的在线网络奠定坚实的基础。 想进一步提升稳定和可扩展&#xff1f;这就是RAID…

【YOLOv8模型onnx部署详解】YOLOv8模型转onnx格式并使用onnxruntime 进行推理部署

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

讲透一个强大算法模型,Transformer !!

好像一直以来都没有和大家讨论过一个贼牛的模型 – Transformer&#xff01; 首先&#xff0c;咱们先用很直白的语言描述一下&#xff1a;想象你在读一本书&#xff0c;每一页都有很多词。如果你每次只能看到一个词&#xff0c;那么理解整本书会很慢。而Transformer模型就像是…

备忘录标签怎么弄 备忘录标签设置方法

在繁忙的生活中&#xff0c;我们常常需要记录各种琐事、工作任务和灵感闪现。备忘录成了我们不可或缺的助手&#xff0c;但随着时间的推移&#xff0c;备忘录里的内容越来越多&#xff0c;如何高效地管理和查找这些信息成了一个大问题。这时&#xff0c;备忘录的标签功能就显得…

TDengine 推出新连接器,与 Wonderware Historian 无缝连接

在最新发布的TDengine 3.2.3.0 版本中&#xff0c;我们进一步更新了 TDengine 的数据接入功能&#xff0c;推出了一款新的连接器&#xff0c;旨在实现 Wonderware Historian&#xff08;现称为 AVEVA Historian&#xff09;与 TDengine 的集成。这一更新提供了更加便捷和高效的…

【新手友好】计算机SCI期刊,IF=3+,编辑负责,修改稿件认真

一、期刊名称 Journal of Communications and Networks 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;3.6 中科院分区&#xff1a;3区 三、期刊征稿范围 《通信与网络杂志》每年出版六期&#xff0c;致力于发表高质量的…

【NeRF】ExtraNeRF:基于扩散模型的NeRF可见性视角外延

项目主页&#xff1a;https://shihmengli.github.io/extranerf-website/ 来源&#xff1a;华盛顿大学&#xff0c;康奈尔大学&#xff0c;谷歌研究&#xff0c;加州大学伯克利分校 标题&#xff1a;ExtraNeRF: Visibility-Aware View Extrapolation of Neural Radiance Fields …

OurBMC运营委员会2024年上半年度例会顺利召开

6 月 27 日&#xff0c;OurBMC 社区运营委员会 2024 年上半年度例会顺利召开。本次会议采用线上线下结合的方式&#xff0c;各委员在会上听取了 2024 年上半年社区运营委员会的工作总结汇报&#xff0c;并规划了下半年运营重点工作&#xff0c;同时针对社区活动改进、运营规划开…

【系统架构设计师】七、信息安全技术基础知识(网络安全技术|网络与信息安全风险|网络安全协议)

目录 一、网络安全技术 1.1 防火墙 1.2 入侵检测系统IDS 1.3 入侵防御系统IPS 1.4 杀毒软件 1.5 蜜罐系统 二、网络与信息安全风险 三、网络安全协议 四、相关推荐 五、历年真题练习 一、网络安全技术 1.1 防火墙 防火墙是在内部网络和外部因特网之间增加的一道安全…

四川赤橙宏海商务信息咨询有限公司抖音开店靠谱吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业正以前所未有的速度发展。而在这个大潮中&#xff0c;四川赤橙宏海商务信息咨询有限公司凭借其专业的团队和前瞻性的战略眼光&#xff0c;专注于抖音电商服务&#xff0c;为广大商家提供了一站式解决方案&#xff0c;成为了行业…