Clickhouse分享

项目终于结束,有了一周左右喘口气的机会,这里学习了下clickhouse,为下次部门技术分享做准备。


目录

介绍

性能分析

适合场景

不适合的场景:

使用场景架构

下载地址

然后搭建、使用

单节点安装

命令

集群搭建(基于单节点)

介绍

配置

分发【安装文件】到其他节点

测试

Java连接clickhouse

导入依赖

创建工具类

建表

测试写入

单表与多表sql语句测试

Clickhouse数据导入和导出

遇到的坑:


介绍

Clickhouse是一款由俄罗斯百度yandex公司开源的一款,消耗cpu,不适合实时插入(毫米级),但是可以快速使用sql查询的引擎。

查询最适合的是做实时分析(秒级),实时写入可以通过kafka缓存做批量写入,统计查询,列出的

性能分析

然后评论clickhouse的性能

性能瓶颈(网络)千兆宽带80mb/s:

https://www.csdn.net/tags/NtDagg3sNzQyMC1ibG9n.html

官方性能地址:

性能 | ClickHouse Docs

实际本机测试,单节点(10gb,4core),每秒插入50W(kudu之类的数据库,tdengine也能达到这样的效果)

他是列式存储,读取飞快

行式和列的区别

在这里插入图片描述

 在这里插入图片描述

 压缩比

 主存,是内存。cache是cpu的高速缓存(可以看作cpu的内存),寄存器是cpu中最快的。

注意:有多少cpu吃多少资源,不适合用作接口,提供给客户,频繁调用。

ok,既然作为一个疯狂无情的吃cpu机器,有没有什么办法能够定义它的控制资源呢?

参考:【ClickHouse内核】资源管理_Night_ZW的博客-CSDN博客_clickhouse 资源管理参数

对于内存,可以针对不同的用户进行控制。

对于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-常用表引擎详解 - 码农教程

适合场景

下面我们说一下,什么场景使用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

代码生产方式插入数据

  1. insert 多个values
  2. 批量写入伪代码如下:
        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模板

对比参考:

clickhouse与mysql查询速度对比_Aiky哇的博客-CSDN博客_clickhouse查询速度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值