ClickHouse性能提升

Stella981
• 阅读 622

本文经作者授权,独家转载:

作者主页:https://www.jianshu.com/u/8f36a5e63d18

1. 不要用select *

反例:

select * from app.user_model

正例:

select login_id,name,sex from app.user_model

理由:    只查询需要的字段可以减少磁盘io和网络io,提升查询性能

2.不要在大结果集上构造虚拟列

反例:

select id ,pv, uv , pv/uv rate from app.scene_model

正例:

select id ,pv, uv from app.scene_model

理由:    虚拟列非常消耗资源浪费性能,拿到pv uv后在前端显示时构造比率。

3. 不要在唯一列或大基数列上进行分组或去重操作

反例:

select id, count(1) cn from app.user_model group by id

正例:

select id  from app.user_model

理由:    基数太大会消耗过多的io和内存。

4. 根据需要查询指定范围的数据 (where)

反例:

select login_id,name,sex from app.user_model

正例:

select login_id,name,sex from app.user_model where create_time>'2020-03-30'

理由:    减少磁盘io和网络io,提升查询性能

5. 关联查询时小表在后(大表 join 小表)

反例:

select login_id,name,sex,a.scene_name from app.scene_model a join app.user_model b on a.create_user=b.id

正例:

select login_id,name,sex,a.scene_name from app.user_model  a join app.scene_model  b on a.id=b.create_user

理由:

    无论是Left Join 、Right Join还是Inner Join永远都是拿着右表中的每一条记录到左表中查找该记录是否存在。

6. 使用 uniqCombined 替代 distinct

反例:

SELECT count( DISTINCT create_user ) from  app.scene_model

正例:

SELECT uniqCombined( create_user ) from  app.scene_model

理由:    uniqCombined对去重进行了优化,通过近似去重提升十倍查询性能

7. 通过使用 limit 限制返回数据条数

反例:

select id,scene_name,code,pv from app.scene_model order by pv desc

正例:

select id,scene_name,code,pv from app.scene_model order by pv desc limit 100

理由:

    使用limit返回指定的结果集数量,不会进行向下扫描,大大提升了查询效率。

8. 尽量不去使用字符串类型

反例:

CREATE TABLE scene_model``( id String, scene_name String, pv String, create_time String``)``ENGINE = <Engine>``...

正例:

CREATE TABLE scene_model``( id String, scene_name String, pv Int32, create_time Date``)``ENGINE = <Engine>``...

理由:

时间类型最终会转换成数值类型进行处理,数值类型在执行效率和存储上远好过字符串。

9. 指定查询分区获取必要的数据

假设分区字段是day
反例:

select type,count(1) from app.user_model group by type

正例:

select type,count(1) from app.user_model where day ='2020-03-30' group by type

理由:    通过指定分区字段会减少底层数据库扫描的文件数量,提升查询性能

10.分组前过滤不必要的字段

反例:

select type,count(1) from app.user_model group by type

正例:

select type,count(1) from app.user_model where type ='1' or  type ='2' group by type

理由:    通过限制分组前结果集数量,查询性能一般能提示数十倍,甚至上百倍

推荐阅读:

clickhouse数据模型之用户路径分析

ClickHouse 数据存储架构优化

基于 Spark 技术快速构建数仓项目

ClickHouse性能提升

本文分享自微信公众号 - 大数据群英萃(BigDataToBeGod)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
Easter79 Easter79
2年前
sql注入(利用join进行无列名注入)
select1,2,3unionselectfromsc;select1from(select1,2,3unionselectfromsc)a;select2from(select1,2,3unionselectfromsc)a;select\fro
Stella981 Stella981
2年前
Mybatis Plus代码方式实现多表关联查询
 Mapper接口如下:例1@Select("SELECTt\_question.\,t\_student.\name\FROMt\_question,t\_studentWHEREt\_question.student\_idt\_student.id")List<QuestionStudentVOgetQ
Wesley13 Wesley13
2年前
oracle语法
 oracle分页(PageingQuery) select\ from   (selectrownumr,e1.\   from(select\fromemporderbysal)e1    whererownum<8   ) wherer5;SQL/\
Wesley13 Wesley13
2年前
Oracle——分页查询
查询员工表中,工资排名在1020之间的员工信息。select  from(    selectrownumrn,employee_id,salary      from(        selectemployee_id,salary,last_name        fromem
Wesley13 Wesley13
2年前
mysql timestamp
 select from\_unixtime(m.createdAt, '%Y%m%d %H:%i:%s') from kfrobotaidlog m;select m.customeruid, from\_unixtime(m.createtime, '%Y%m%d %H:%i:%s') as \datetime\, m.kfui
Wesley13 Wesley13
2年前
oracle游标的例子
declare    cursor ca is select id_no, name from user where ym201401;begin    for cb in ca loop        update path set enamecb.name where id_nocb.id
Stella981 Stella981
2年前
Bypass ngx_lua_waf SQL注入防御(多姿势)
0x00前言ngx\_lua\_waf是一款基于ngx\_lua的web应用防火墙,使用简单,高性能、轻量级。默认防御规则在wafconf目录中,摘录几条核心的SQL注入防御规则:select.(from|limit)(?:(union(.?)select))(?:from\Winformation_schema\W)这边
Stella981 Stella981
2年前
Merge Into 语法
mergeinto根据查询数据对已存在的表中数据执行删除、修改、新增操作,在实际应用中非常实用,可以减少insert、update、delete的书写。基本语法:merge into table_name tn using (select column_name,... from table_name ) tmp on tn.条件tm
Wesley13 Wesley13
2年前
mysql _01
\where中不可以使用别名,因为where先于select执行以下是错误的SQL:select    code,   continentcont,   name,   populationpop from    country where    cont'asia'
Wesley13 Wesley13
2年前
mysql查询数据
今天:select\from表名whereto\_days(时间字段名)to\_days(now());昨天SELECT\FROM表名WHERETO\_DAYS(NOW())TO\_DAYS(时间字段名)<1近七天SELECT\FROM表名whereDATE\_SUB