7.ClickHouse系列之查询优化

1. Explain查询计划查看

// 查看执行计划,默认值
EXPLAIN PLAN SELECT arrayJoin([6,6,7])
// AST语法树查看
EXPLAIN AST SELECT numbers FROM system.numbers LIMIT 10;
// 用于优化语法
EXPLAIN SYNTAX SELECT arrayJoin([6,6,7])
// 查看PIPELINE计划
EXPLAIN PIPELINE SELECT arrayJoin([6,6,7])

2. 建表优化

2.1 数据类型

  • 时间字段类型:建表时能用数值型或日期时间表示的字段就不要用字符串。虽然ClickHouse底层将DateTime存储为时间戳Long类型,但不建议存储Long类型,因为DateTime不需要经过函数转换处理,执行效率高,可读性好
  • 空值存储类型:官方指出Nullable类型几乎总是会拖累性能。因为存储Nullable列时需要创建一个额外的文件来存储NULL的标识(具体var/lib/clickhouse/data/table/column.null.bin),并且Nullable列无法被索引。应直接使用字段默认值表示空,或者自行指定一个在业务中无意义的值

2.2 分区与索引

分区粒度根据根据业务特点决定,不宜过粗过细。一般选择按天分区。必须指定索引列,ClickHouse中索引列即排序列,通过order by指定。组合索引需满足查询频率大在前。基数特别大的列不适宜做索引列

3 ClickHouse内部语法优化规则

3.1 Count优化

如果使用的是count()或count(*),只要没指定具体字段,且没有where条件,则会直接使用system.tables的total_rows:

SELECT COUNT() FROM datasets.hits_vl;

3.2 子查询\ORDER BY\LIMIT BY\USING KEY重复字段会自动消除

3.3 谓词下推

EXPLAIN SYNTAX SELECT UserID FROM hits_v1 GROUP BY UserID Having UserID='111';
会被自动优化为
EXPLAIN SYNTAX SELECT UserID FROM hits_v1 WHERE UserID='111' GROUP BY UserID;

3.4 聚合函数外推

EXPLAIN SYNTAX SELECT SUM(UserID*2) FROM visits_v1;
会被自动优化为
SELECT SUM(UserID) * 2 FROM visits_v1;

3.5 聚合函数消除

EXPLAIN SYNTAX SELECT SUM(UserID*2),max(VisitID), max(UserID) FROM visits_v1 GROUP BY UserID;
会被自动优化为
EXPLAIN SYNTAX SELECT SUM(UserID) * 2, max(VisitID), UserID FROM visits_v1 GROUP BY UserID;

3.6 三元运算优化

EXPLAIN SYNTAX SELECT number=1?'hello':(number=2?'world':'china') FROM numbers(10) SETTINGS optimize_if_chain_to_multiif=1;
返回优化后的语句:
─explain───────────────────────────────────────────────────────────┐
│ SELECT multiIf(number = 1, 'hello', number = 2, 'world', 'china') │
│ FROM numbers(10)                                                  │
│ SETTINGS optimize_if_chain_to_multiif = 1                         │
└───────────────────────────────────────────────────────────────────┘

4 单表查询优化

4.1 prewhere代替where

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

4.2 数据采样

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

SELECT Title, count(*) AS PageViews FROM hits_v1 SAMPLE 0.1 WHERE CounterID=57 GROUP BY Title;

4.3 列裁剪与分区裁剪

列裁剪即指定所需要的列,而非全量*,分区裁剪就是只读取需要的分区,在过滤条件中指定

4.4 order by结合where limit

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

4.5 避免构建虚拟列

不要在结果集上构建虚拟列,非常消耗资源降低性能。

// 反例
SELECT Income, Age, Income/Age AS Ia FROM datasets.hits_v1;

4.6 uniqCombined替代distinct

性能可提升10倍以上,uniqCombined底层采用类似HyperLogLog算法实现。不建议在千万级数据上执行distinct去重查询,改为近似去重uniqCombined。

4.7 考虑使用物化视图

ClickHouse的物化视图是一种查询结果的持久化。物化视图不会随着基础表的变换而变化,被称为’快照’,
如下表而言,当发布日期大于10月1日,会在物化视图的存储表.inner_id.xxxx中插入数据,而当清空基础表house时,.inner_id.xxxx中的数据并不会丢失。

// 创建物化视图
CREATE MATERIALIZED VIEW study.house_new_mv ENGINE ReplacingMergeTree PARTITION BY toYYYYMMDD(publish_date) ORDER BY(id, city, region, name)
AS SELECT id, city, region, name, publish_date FROM study.house WHERE publish_date > toDate('2022-10-01');
// 插入数据
INSERT INTO study.house VALUES (2, '上海', '静安', '彭一小区', 70000, toDateTime('2022-05-06'));
INSERT INTO study.house VALUES (2, '上海', '静安', '彭一小区', 70000, toDateTime('2022-10-06'));
TRUNCATE TABLE study.house;
SELECT * FROM study.house_new_mv;

3

5. 用IN代替JOIN

当多表查询时,查询的数据仅从一张表出时,可考虑用IN操作而不是JOIN

SELECT a.* FROM hits_v1 a WHERE a.CounterID in (SELECT CounterID FROM visits_v1);

6. 多表JOIN小表在右

右表关联时被加载到内存与左表进行对比,所以多表JOIN时右表必须是小表。

7. 注意谓词下推

ClickHouse在join查询时不会主动发起谓词下推的操作,需要每个子查询提前完成过滤操作。新版本不存在此问题,可以在查询时EXPLAIN SYNTAX

8. 分布式表使用gobal

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

欢迎关注公众号算法小生或沈健的技术博客shenjian.online

### 回答1: ClickHouse是一个快速、可扩展的列式数据库,支持GIS(地理信息系统)查询。它提供了一套用于处理空间数据的函数和工具,可以轻松执行各种GIS相关查询。以下是关于ClickHouse GIS查询的一些概述: 1. 空间数据存储:ClickHouse可以存储和管理包含空间信息的数据,例如点、线、多边形等。这些空间数据可以直接存储在ClickHouse表中的特定列中。 2. 空间索引:ClickHouse使用R-树索引来管理空间数据。这种索引结构允许高效的空间查询,如范围查询、邻近查询和空间连接查询。 3. 空间函数:ClickHouse提供了一系列内置的空间函数,用于处理和分析空间数据。这些函数包括计算距离、计算面积、判断点是否在某个区域内等功能。 4. 空间查询:通过使用ClickHouse的空间函数,可以执行各种空间查询,如查找在给定区域内的点、查找与给定点最近的点、在多个区域之间进行空间连接等。 5. 运算符和语法:ClickHouse支持使用标准SQL语句进行空间查询,例如使用WHERE子句来过滤和筛选空间数据,使用SELECT子句来选择和投影空间数据。 6. 性能优化ClickHouse通过设计优化查询引擎和列式存储方式,可以高效地处理大规模的空间数据。此外,它还支持水平扩展,可以在需要时轻松添加更多的资源来处理复杂的GIS查询。 总的来说,ClickHouse提供了一套功能强大的工具和函数,用于处理和查询GIS数据。无论是进行空间分析还是空间可视化,ClickHouse都是一个可靠和高效的解决方案。 ### 回答2: ClickHouse是一种高性能且可扩展的列式数据库管理系统。它还提供了GIS(地理信息系统)功能,使得可以在地理空间中进行查询和分析。 使用ClickHouse进行GIS相关查询可以实现以下功能: 1. 空间数据类型支持:ClickHouse可以存储和处理空间数据类型,例如点、线、面等。这些数据类型可以用来表示地理要素,如地点、道路、建筑物等。 2. 空间索引:ClickHouse提供了空间索引的支持,可以针对空间数据进行高效的查询。空间索引可以加快空间数据的查询速度,提高查询性能。 3. 空间查询操作:ClickHouse提供了一些用于空间查询的函数,例如计算两个几何对象之间的距离、判断一个点是否在一个区域内等。通过这些函数,可以执行一些与地理位置相关的查询操作。 4. 空间查询优化ClickHouse还提供了一些优化技巧,以提高空间查询的性能。例如,可以对空间数据进行分区和排序,以减少查询时的数据扫描量。 总之,ClickHouse提供了强大的GIS功能,使得可以在地理空间中进行高效的查询和分析。无论是需要处理地理数据的应用场景,还是需要空间分析的业务需求,ClickHouse都可以胜任。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小生Đ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值