项目终于结束,有了一周左右喘口气的机会,这里学习了下clickhouse,为下次部门技术分享做准备。
目录
介绍
Clickhouse是一款由俄罗斯百度yandex公司开源的一款,消耗cpu,不适合实时插入(毫米级),但是可以快速使用sql查询的引擎。
查询最适合的是做实时分析(秒级),实时写入可以通过kafka缓存做批量写入,统计查询,列出的
性能分析
然后评论clickhouse的性能
性能瓶颈(网络)千兆宽带80mb/s:
https://www.csdn.net/tags/NtDagg3sNzQyMC1ibG9n.html
官方性能地址:
实际本机测试,单节点(10gb,4core),每秒插入50W(kudu之类的数据库,tdengine也能达到这样的效果)
他是列式存储,读取飞快
行式和列的区别
压缩比
主存,是内存。cache是cpu的高速缓存(可以看作cpu的内存),寄存器是cpu中最快的。
注意:有多少cpu吃多少资源,不适合用作接口,提供给客户,频繁调用。
ok,既然作为一个疯狂无情的吃cpu机器,有没有什么办法能够定义它的控制资源呢?
对于内存,可以针对不同的用户进行控制。
对于cpu,可以针对不同的用户设定优先级。(这里的用户指的是数据库用户)
----对于业务来说,可以做分离,对于不同的业务需求要求性,定义不同的用户,去做限制。不能对单个sql去进行限制。
对于io,clickhouse暂时不支持做限制。
对于资源配置限额,约束的是查询,可以根据ip(指的是后端调用ck的ip),也支持对于用户(数据库用户限额)
总结: 所以,你没法对于不同的请求,进行限额,只能部署在不同的ip,或者添加数据库用户,不过这个不可取。
存储引擎可以当作为,hive的存储格式(textfile,orc,parquet),或者mysql的存储引擎,myisam,InnoDB
下面的适合场景,是对clickhouse的整体场景,那如果具体一点涉及到的表引擎,适合哪些业务场景的具体案例呢?
表引擎是 ClickHouse 的一大特色。可以说, 表引擎决定了如何存储表的数据。包括:
➢ 数据的存储方式和位置,写到哪里以及从哪里读取数据。
➢ 支持哪些查询以及如何支持(不同引擎有些功能不能用)。
➢ 并发数据访问。
➢ 索引的使用(如果存在)。
➢ 是否可以执行多线程请求。
➢ 数据复制参数。
表引擎的使用方式就是必须显式在创建表时定义该表使用的引擎,以及引擎使用的相关参数。
特别注意:引擎的名称大小写敏感
下面这张图,是我汇总了下面所有参考做的一张图,方便大家在不同需要时使用
引擎类型-系列 衍生物 特点 应用场景 MergeTree 系列说明 ck中最强大的引擎 支持索引和分区,地位可以相当于 innodb 之于 Mysql MergeTree 支持一个日期和一组主键的两层式索引,还可以实时更新数据。
同时,索引的粒度可以自定义,外加直接支持采样功能。是其他merge子类的父类 ReplacingMergeTree 添加了“处理重复数据”的功能 实时数据场景中获取最新数据 AggregatingMergeTree 针对聚合函数结果,作增量计算优化 CollapsingMergeTree 是专门为 OLAP 场景下,一种“变通”存数做法而设计的 Log 系列说明 ck中最小功能的轻量级引擎 写入与操作大量小表(小表最大数据为100W),这种场景用它 TinLog 最简单的表引擎,用于将数据存储在磁盘上,数据不分块,只支持并发读 测试或多小表场景 Log 数据分块记录偏移量,并发读写、支持多线程处理、mark.mrk 数据块标记文件、不支持索引 StripeLog 该引擎index.mrk 对数据建立了索引、支持并发读写,
在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎Integration 系列说明 操作外部数据源,加载外部数据库 可以直接加载mysql和hdfs的数据 HDFS 该引擎里面的数据不能变动,只能一次性加载 加载hdfs数据 MySQL 可以查询数据 ,也可以向表中插入数据,不支持删除和更新操作 加载mysql数据 File 加载文件,如CSV Special 系列说明 针对特殊需要,生产环境用的非常少 请看不同的子衍生物 Memory 数据存储在内存中,不会压缩不会格式转换,速度非常快 ck内部使用,高性能测试使用(上限为1亿行数据) Set 数据存储在内存中,然后被同步到磁盘上 自带去重效果 Buffer 与memory类似,定期将缓冲刷新到另一个表 充当缓冲角色 Null 物化视图,不保留原表数据 Live View 特殊视图 监控sql查询结果,如果增加,则会响应
参考:
ClickHouse不同引擎大比拼 - 腾讯云开发者社区-腾讯云
大数据之clickhouse各类引擎_大数据同盟会的博客-CSDN博客_clickhouse的引擎
适合场景
下面我们说一下,什么场景使用clickhouse
当你有几TB,甚至PB数据时,需要全量数据分析,又要求分析快速的时候,可以采用clickhouse
当你需要一张大宽表的时候,其他的性能指标都是基于宽表的,可以采用clickhouse
适合数据实时数据分析BI展示
大于1000条(适合,适合低频高量),每秒几十万的写入。
Java写入(第三方开源,前期速度快,后期没有官方快)
GitHub - housepower/ClickHouse-Native-JDBC: ClickHouse Native Protocol JDBC implementation
结果是聚合的结果。查询非常快,展示的列少,统计的结果非常快,大概是mysql的几百倍。
适合存储大量的日志和记录,作为分析使用。
不适合的场景:
不支持多查询(单查询会调用很大的cpu,多查询会宕机),所以不要提供接口,而是直接用来分析展示。
插入建议一次性批量写入(不支持高频低量)
他是列式数据库,列式数据库都不支持事务,所以不适合做业务数据库。
使用场景架构
下载地址
https://repo.clickhouse.com/tgz/
安装方式有rpm,yum,docker,tgz等,这里采用tgz
我使用的是20.2.1.2120版本
Ctrl+f搜索,后下载。
static和static-dbg以及server和client
准备文件:
然后搭建、使用
单节点安装
将4个文件,上次到服务器上,我喜欢上传到我自己建的文件夹(software)目录下。
解压,先解压静态资源(含static的)
解压后,进入install目录,执行他的安装脚本
./doinst.sh
解压第二个静态资源
同样./doinst.sh
解压服务端
./doinst.sh
解压客户端
./doinst.sh
安装比较简单,结束,安装后,他会自动写入系统默认环境变量目录(usr-bin),所以能够直接输入命令
开启支持ipv4
cd /etc/clickhouse-server
vi config.xml
-----------------
开启listen_host(去掉他的注释,IPV4)
<listen_host>0.0.0.0</listen_host>
-----------------
给予其他用户读写clickhouse的权限
chown -R root:root /var/lib/clickhouse /var/log/clickhouse-server /etc/clickhouse-server /etc/clickhouse-client
设置密码
vi users.xml
用户默认叫default
命令
版本不同,控制命令稍有不同
我的版本是20.2.1.2120
查看clickhouse有哪些命令
clickhouse --help
启动命令(必须指定配置文件,否则会not found)
clickhouse-server --config-file=/etc/clickhouse-server/config.xml start
启动客户端(必须指定ip地址)
clickhouse-client -h 192.168.30.101
clickhouse-client -h localhost --port 9000 -u default --password 123456 ;
集群搭建(基于单节点)
介绍
Clickhouse依赖的是zookeeper,他是【非】主从架构,节点独立。
比如,他能够3个节点,建立2个集群
集群配置有2种
第一种直接在config.xml里配置
第二种在metrika.xml中配置,然后在config.xml引用前者的地址
我在我的版本里面没有找到metrika.xml。所以这里直接使用第一种方法进行配置。
Clickhouse牛逼的是,你配置完不需要重启,他自动热加载。
我们拿3台节点搭建一个ck集群玩一下。
先把之前搭建的单节点,进行配置。
配置
cd /etc/clickhouse-server
vi config.xml
找到下面这段
从<test_shard_localhost>进行修改,这个是集群的名称,改为<test_1>
更改内容如下:
修改的内容如下:
<!--自定义集群名称-->
<test_1>
<!--定义集群的分片数量,3个shard标签说明有3个节点-->
<shard>
<!--定义分片的副本数量,这里副本只有1个-->
<replica>
<host>hadoop1</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>hadoop2</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>hadoop3</host>
<port>9000</port>
</replica>
</shard>
</test_1>
插入的zookeeper配置如下:(zookeeper在</test_1>下方)
<zookeeper-servers>
<node index="1">
<host>hadoop1</host>
<port>2181</port>
</node>
<node index="2">
<host>hadoop2</host>
<port>2181</port>
</node>
<node index="3">
<host>hadoop3</host>
<port>2181</port>
</node>
</zookeeper-servers>
分发【安装文件】到其他节点
scp -r ck root@hadoop3:/software/ck
scp -r ck root@hadoop2:/software/ck
走单节点的搭建,剩下的两台机器各种install后。
分发刚刚改的配置文件
scp /etc/clickhouse-server/config.xml root@hadoop3:/etc/clickhouse-server/config.xml
scp /etc/clickhouse-server/config.xml root@hadoop2:/etc/clickhouse-server/config.xml
其他节点启动
因为安装后,数据文件默认是clickhouse用户的,必须用clickhouse用户才能启动
sudo -u clickhouse clickhouse server --config-file=/etc/clickhouse-server/config.xml start
测试
参考文章:
ClickHouse集群搭建部署_疯狂哈丘的博客-CSDN博客_clickhouse集群搭建
Java连接clickhouse
导入依赖
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.1.52</version>
</dependency>
创建工具类
package tools;
import ru.yandex.clickhouse.ClickHousePreparedStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
//大宽表,bi用
public class DBClickHouse {
String driverName="ru.yandex.clickhouse.ClickHouseDriver";
String url="jdbc:clickhouse://192.168.30.101:8123/test";
String user="default";
String password="root";
public Connection getConnection() {
Connection conn = null;
{
try {
Class.forName(driverName);
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return conn;
}
public void close(AutoCloseable... closes) {
for (AutoCloseable close : closes) {
if (close!=null) {
try {
close.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
close=null;
}
}
}
}
//增加和删除
public boolean insertOrdelete(Connection connection, String sql, String... params) {
boolean b =false;
ClickHousePreparedStatement pst=null;
if (connection==null) {
System.out.println("connection is empty");
System.exit(-1);
}
try {
pst= (ClickHousePreparedStatement) connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pst.setObject(i+1,params[i]);
}
b= pst.execute();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
close(pst,connection);
}
return b;
}
//查询
public ResultSet QueryResultSet(Connection connection, String sql, String... params) {
ResultSet rst=null;
ClickHousePreparedStatement pst=null;
if (connection==null) {
System.out.println("connection is empty");
System.exit(-1);
}
try {
pst= (ClickHousePreparedStatement) connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pst.setObject(i+1,params[i]);
}
rst = pst.executeQuery();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
close(rst,pst,connection);
}
return rst;
}
}
建表
建表参考:Clickhouse创建表 - jason_wei - 博客园
数据类型参考:ClickHouse的数据类型介绍 - 渐逝的星光 - 博客园
建了一个测试表(不知道用什么引擎,就选用mergeTree)
例子:
我建立的:
CREATE TABLE test(name1 String,name2 String,name3 String,name4 String,name5 String,name6 String,name8 String,name9 String,name10 String,name11 String,name12 String,name13 String)ENGINE = MergeTree()order by name1
测试写入
日志方式
tail -F apapche/access.log | sendtoclick -h tcp://127.0.0.1:9000
代码生产方式插入数据
- insert 多个values
- 批量写入伪代码如下:
for (int i = 0; i < size; i++) {
preparedStatement.setObject(j , value);
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
connection.commit();
preparedStatement.clearBatch();
我一般批量value,加批量写入。
java创建了100W条简单数据,用时测试,1秒内
测试,clickhouse插入速度
Java代码如下:
import tools.DBClickHouse;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
public class CkTest {
public static void main(String[] args) throws SQLException {
Connection connection = DBClickHouse.getConnection();
String sql="insert into test values(?,2,3,4,5,6,7,8,9,10,11,12)";
//测试每秒产生数据量
System.out.println("开始时间"+new Date().toString());
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < 1000000; i++) {
preparedStatement.setObject(1,i);
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
connection.commit();
System.out.println("结束时间"+new Date().toString());
}
}
运行结果
100w条数据,单节点,3秒内插入完成
每秒35W左右的速度,没有做任何配置和优化
当设置了一千万为一批次,用了20秒,相当于总共每秒50W
升级硬件测试:
增加核数,插入测试,因为之前是4核,于是改成了8核,插入速度没有改变
改成多线程插入测试:
增加了10个线程,每个线程批量处理100W数据,发现速度没有明显变化,25秒插入完成,差不多每秒40W左右
最后也在网上看了些优化,他们也是批量插入,用的mergeTree引擎,速度也是二十多万每秒。
好像感觉他的插入瓶颈比较低,目前在github上提问,还没有得到答案
在群里问,他们说瓶颈是io,是硬盘。问了github,给的答案请看
What is the insertion speed of clickhouse? · Issue #42374 · ClickHouse/ClickHouse · GitHub
单表与多表sql语句测试
首先我准备了2张表,test和test1
test有2000w数据,test1有1000w数据
首先测试count,单表的统计,快的恐怖
然后测试,单表的group by稍微复杂的分组统计,0.2秒依旧快的恐怖
他默认只显示前1W行数据.
连表查询
(查询优化,默认将数据小的放左边,这样可以提高内存利用率)
连表统计,千万级,依旧可以接受
连表group by,这个算是难度大了,首先关联表,然后在分组,数据比较多
我写了个笛卡尔积的sql,报错了
提示内存不足
只要注意sql就可以。clickhouse的sql优化是比较弱的。
sql优化测试,参考:
https://www.jianshu.com/p/ff015e260374
单表精准查询,测试飞快
单表模糊匹配查询
飞快,也可能与我数据有关,因为我的数据是单字节的
多表模糊查询匹配
笛卡尔积,服务直接挂了,所以说,开副本还是非常有必要。
总结:clickhouse查询,还是不要主动提供出来让别人来查询sql,不要作为谁都可以调用的使用,万一谁写了个sql,整个机器挂了。就出大问题了。
Clickhouse数据导入和导出
二、clickhouse数据导入导出的N种方式
(1)、sql文件形式的导入导出
sql导出: echo 'select * from table_name' | curl ip:8123?database=database_name -uuser:password -d @-> table name so
sql导入:cat tablename.sql | clickhouse-client -hip -uuser --password password --query="INSERT INTO db_name.table_name FORMAT TabSeparated"
(2)、CSV文件形式的导入导出
CSV导出:clickhouse-client -h 127.0.0.1 --datahase="db" -m -n --format_csv_delimiter="," --query="select * from db_name.table_name FORMAT CSV" > tahle_name csv
CSV导入:clickhouse-client -h 127.0.0.1 --database="db" -m -n --format_csv_delimiter="," --query="insert into db_name.table_name FORMAT CSV" < table_name.csv
注意:如果query语句后面不加FORMAT CSV,默认是\t作为分隔符。只有指定FORMAT CSV后,指定--format_csv_delimiter才生效。
clickhouse-client的常用参数
-C --config-file 配置文件目录
-c --config 配置文件目录
-h --host 服务器ip地址
--port 指定端口
-u --user 指定用户名
--password 指定密码
--ask-password 询问密码
-q --query 指定SQL
-d --database 指定数据库
-m --multiline 多行组合成一个sql执行。
-n --multiquery 一次执行多个SQL,SQL之间使用’;'分号隔离
--queries-file 指定SQL文件(file1 file2)
-f --format 输出格式
-t --time 在非交互式格式中将执行时间打印到错误日志中。
--format_csv_delimiter 指定CSV数据中的列分隔符。 默认情况下分隔符为逗号(,)。
参考:
clickhouse导入和导出 - 业余砖家 - 博客园 (cnblogs.com)
样例sql文件导入导出
clickhouse导出为sql
导出数据
clickhouse导出sql(下面这个root是我的密码,我的密码叫root,我也不知道当时咋想的:)
echo 'select * from car_info' | curl 192.168.30.101:8123?database=default -udefault:root -d @- > car_info.sql
导出表结构
show create table tablename,把第一条的语句改成这个就可以导出表结构了。
1.把刚刚导出的表结构sql,放到另一台服务器上
clickhouse-client -h192.168.9.104 --user default --password default -d default < /car_info_des.sql
2.将导出的数据,放在另一台服务器上
cat car_info.sql | clickhouse-client -h192.168.9.104 --user default --password default --query="INSERT INTO default.car_info FORMAT TabSeparated"
遇到的坑:
<Error> Application: DB::Exception: Effective user of the process (root) does not match the owner of the data (clickhouse). Run under 'sudo -u clickhouse'.
解决:
sudo -u clickhouse 在后面加上你的命令
如:sudo -u clickhouse clickhouse-server start
默认不支持ipv4,需要在配置中开启,否则将无法启动clickhouse服务端
Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = File not found: config.xml0. 0xbc5b01c Po
解决:
cd /etc/clickhouse-server
vi config.xml
-----------------
开启listen_host(去掉他的注释,IPV4)
<listen_host>0.0.0.0</listen_host>
图中是开启ipv6,系统支持哪个就开放哪个
-----------------
问题:sudo -u clickhouse clickhouse server start运行启动出错
Include not found: clickhouse_remote_servers
Include not found: clickhouse_compression
Couldn't save preprocessed config to /var/lib/clickhouse//preprocessed_configs/config.xml: Access to file denied: /var/lib/clickhouse//preprocessed_configs/config.xml
Logging trace to /var/log/clickhouse-server/clickhouse-server.log
解决:
clickhouse其他用户没有写入权限,开放这个文件的写入权限
chown -R root:root /var/lib/clickhouse /var/log/clickhouse-server /etc/clickhouse-server /etc/clickhouse-client
clickhouse server start
Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = File not found: config.xml
解决:
必须启动时候指定,配置文件目录
clickhouse-server --config-file=/etc/clickhouse-server/config.xml
启动后,卡在
Include not found: clickhouse_compression
解决:
这是正常的,下面2个只是提示,你的配置没有配置这个,你没有他的需求不需要配置。
此时通过客户端连接:
clickhouse-client -h ip地址
参考文章:
ClickHouse安装部署【非常详细】_苡~的博客-CSDN博客_clickhouse安装
ClickHouse(十四)ClickHouse技术分享ppt_高并发的博客-CSDN博客_技术分享ppt模板
对比参考: