clickhouse基础及搭建

6 阅读11分钟

1.安装

1.修改文件限制
在 hadoop102 的 /etc/security/limits.conf 文件的末尾加入以下内容
[atguigu@hadoop102 ~]$ sudo vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

在 hadoop102 的/etc/security/limits.d/20-nproc.conf 文件的末尾加入以下内容
[atguigu@hadoop102 ~]$ sudo vim /etc/security/limits.d/20-nproc.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

2.执行同步操作
[atguigu@hadoop102 ~]$ sudo /home/atguigu/bin/xsync /etc/security/limits.conf

2.安装软件
sudo yum install -y libtool
sudo yum install -y *unixODBC*

3.设置selinux
修改/etc/selinux/config 中的 SELINUX=disabled
[atguigu@hadoop102 ~]$ sudo vim /etc/selinux/config
SELINUX=disabled


4.执行同步操作
sudo /home/atguigu/bin/xsync /etc/selinux/config


5.安装clickhouse
创建文件夹
mdkir -p /opt/software/clickhouse

上传文件 
clickhouse-client-21.7.3.14-2.noarch.rpm
clickhouse-common-static-21.7.3.14-2.x86_64.rpm
clickhouse-common-static-dbg-21.7.3.14-2.x86_64.rpm
clickhouse-server-21.7.3.14-2.noarch.rpm

6.分发文件
xsync clickhouse

7.分别在每台服务器进行安装文件
sudo rpm -ivh *.rpm

8.在hadoop102修改配置文件
sudo vim /etc/clickhouse-server/config.xml
 
把 <listen_host>::</listen_host> 的注释打开,这样的话才能让 ClickHouse 被除本
机以外的服务器访问

9.分发配置文件
sudo /home/atguigu/bin/xsync /etc/clickhouse-server/config.xml
在这个文件中,有 ClickHouse 的一些默认路径配置,比较重要的
数据文件路径:<path>/var/lib/clickhouse/</path>
日志文件路径:<log>/var/log/clickhouse-server/clickhouse-server.log</log>

10.测试连接(安装时候输入的密码)
clickhouse-client -m -u default --password '123456'

2.数据类型

时间类型
目前 ClickHouse 有三种时间类型
➢ Date 接受年-月-日的字符串比如 ‘2019-12-16’
➢ Datetime 接受年-月-日 时:分:秒的字符串比如 ‘2019-12-16 20:50:10’
➢ Datetime64 接受年-月-日 时:分:秒.亚秒的字符串比如‘2019-12-16 20:50:10.66’
日期类型,用两个字节存储,表示从 1970-01-01 (无符号) 到当前的日期值。

数组
Array(T):由 T 类型元素组成的数组。
T 可以是任意类型,包含数组类型。 但不推荐使用多维数组,ClickHouse 对多维数组
的支持有限。例如,不能在 MergeTree 表中存储多维数组。

创建方式 1,使用 array 函数
hadoop102 :) SELECT array(1, 2) AS x, toTypeName(x) ;

创建方式2
SELECT [1, 2] AS x, toTypeName(x);

3.SQL语句

创建
CREATE TABLE t_enum
(
 x Enum8('hello' = 1, 'world' = 2)
)
ENGINE = TinyLog;

添加数据
INSERT INTO t_enum VALUES ('hello'), ('world'), ('hello');

查询数据
select * from t_enum;

SELECT CAST(x, 'Int8') FROM t_enum;

删除与更新

ClickHouse 提供了 DeleteUpdate 的能力,这类操作被称为 Mutation 查询,它可以看做 Alter 的一种。

虽然可以实现修改和删除,但是和一般的 OLTP 数据库不一样。

Mutation 语句是一种很“重”的操作,而且不支持事务。

“重”的原因主要是每次修改或者删除都会导致放弃目标数据的原有分区,重建新分区。

所以尽量做批量的变更,不要进行频繁小数据的操作。

删除操作
alter table t_order_smt delete where sku_id ='sku_001';

修改操作
alter table t_order_smt update total_amount=toDecimal32(2000.00,2) where id=102;

由于操作比较“重”,所以 Mutation 语句分两步执行,同步执行的部分其实只是进行
新增数据新增分区和并把旧分区打上逻辑上的失效标记。直到触发分区合并的时候,才会删
除旧数据释放磁盘空间,一般不会开放这样的功能给用户,由管理员完成。


修改表结构
1)新增字段
alter table tableName add column newcolname String after col1;
2)修改字段类型
alter table tableName modify column newcolname String;
3)删除字段
alter table tableName drop column newcolname;

4.引擎支持

TinyLog
以列文件的形式保存在磁盘上,不支持索引,没有并发控制。一般保存少量数据的小表,
生产环境上作用有限。
如:create table t_tinylog ( id String, name String) engine=TinyLog;

Memory
内存引擎,数据以未压缩的原始形式直接保存在内存当中,服务器重启数据就会消失。
读写操作不会相互阻塞,不支持索引。简单查询下有非常非常高的性能表现(超过 10G/s)。
一般用到它的地方不多,除了用来测试,就是在需要非常高的性能,同时数据量又不太
大(上限大概 1 亿行)的场景。


MergeTree
ClickHouse 中最强大的表引擎当属 MergeTree(合并树)引擎及该系列(*MergeTree)
中的其他引擎,支持索引和分区,地位可以相当于 innodb 之于 Mysql。而且基于 MergeTree,
还衍生除了很多小弟,也是非常有特色的引擎


ReplacingMergeTree
ReplacingMergeTreeMergeTree 的一个变种,它存储特性完全继承 MergeTree,只是
多了一个去重的功能。 尽管 MergeTree 可以设置主键,但是 primary key 其实没有唯一约束
的功能。如果你想处理掉重复的数据,可以借助这个 ReplacingMergeTree1)去重时机
数据的去重只会在合并的过程中出现。合并会在未知的时间在后台进行,所以你无法预
先作出计划。有一些数据可能仍未被处理。
2)去重范围
如果表经过了分区,去重只会在分区内部进行去重,不能执行跨分区的去重。
所以 ReplacingMergeTree 能力有限, ReplacingMergeTree 适用于在后台清除重复的数
据以节省空间,但是它不保证没有重复的数据出现。

实际上是使用 order by 字段作为唯一键
➢ 去重不能跨分区
➢ 只有同一批插入(新版本)或合并分区时才会进行去重
➢ 认定重复的数据保留,版本字段值最大的
➢ 如果版本字段相同则按插入顺序保留最后一笔


SummingMergeTree
对于不查询明细,只关心以维度进行汇总聚合结果的场景。如果只使用普通的MergeTree
的话,无论是存储空间的开销,还是查询时临时聚合的开销都比较大。
ClickHouse 为了这种场景,提供了一种能够“预聚合”的引擎 SummingMergeTree
➢ 以 SummingMergeTree()中指定的列作为汇总数据列
➢ 可以填写多列必须数字列,如果不填,以所有非维度列且为数字列的字段为汇总数据列
➢ 以 order by 的列为准,作为维度列
➢ 其他的列按插入顺序保留第一行
➢ 不在一个分区的数据不会被聚合
➢ 只有在同一批次插入(新版本)或分片合并时才会进行聚合

5.partition by,order by,group by

primary key 主键(可选)

ClickHouse 中的主键,和其他数据库不太一样,它只提供了数据的一级索引,但是却不
是唯一约束。这就意味着是可以存在相同 primary key 的数据的。
主键的设定主要依据是查询语句中的 where 条件。
根据条件通过对主键进行某种形式的二分查找,能够定位到对应的 index granularity,避
免了全表扫描。
index granularity: 直接翻译的话就是索引粒度,指在稀疏索引中两个相邻索引对应数
据的间隔。ClickHouse 中的 MergeTree 默认是 8192。官方不建议修改这个值,除非该列存在
大量重复值,比如在一个分区中几万行才有一个不同数据。

稀疏索引:稀疏索引的好处就是可以用很少的索引数据,定位更多的数据,代价就是只能定位到索
引粒度的第一行,然后再进行进行一点扫描。

order by(必选)

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

GROUP BY 

GROUP BY操作增加了 with rollup\with cube\with total 用来计算小计和总计。

alter table t_order_mt delete where 1=1;
insert into t_order_mt values
(101,'sku_001',1000.00,'2020-06-01 12:00:00'),
(101,'sku_002',2000.00,'2020-06-01 12:00:00'),
(103,'sku_004',2500.00,'2020-06-01 12:00:00'),
(104,'sku_002',2000.00,'2020-06-01 12:00:00'),
(105,'sku_003',600.00,'2020-06-02 12:00:00'),
(106,'sku_001',1000.00,'2020-06-04 12:00:00'),
(107,'sku_002',2000.00,'2020-06-04 12:00:00'),
(108,'sku_004',2500.00,'2020-06-04 12:00:00'),
(109,'sku_002',2000.00,'2020-06-04 12:00:00'),
(110,'sku_003',600.00,'2020-06-01 12:00:00');

with rollup:从右至左去掉维度进行小计
with cube : 从右至左去掉维度进行小计,再从左至右去掉维度进行小计
with totals: 只计算合计

6.TTL

数据 TTL
TTLTime To LiveMergeTree 提供了可以管理数据表或者列的生命周期的功能。

列级别 TTL1)创建测试表
create table t_order_mt3(
 id UInt32,
 sku_id String,
 total_amount Decimal(16,2) TTL create_time+interval 10 SECOND,
 create_time Datetime
) engine =MergeTree
partition by toYYYYMMDD(create_time)
 primary key (id)
 order by (id, sku_id);
 
(2)插入数据(注意:根据实际时间改变)
insert into t_order_mt3 values
(106,'sku_001',1000.00,'2020-06-12 22:52:30'),
(107,'sku_002',2000.00,'2020-06-12 22:52:30'),
(110,'sku_003',600.00,'2020-06-13 12:00:00');

(3)手动合并,查看效果 到期后,指定的字段数据归 0
optimize table t_order_mt3 final


表级 TTL
下面的这条语句是数据会在 create_time 之后 10 秒丢失
alter table t_order_mt3 MODIFY TTL create_time + INTERVAL 10 SECOND;
涉及判断的字段必须是 Date 或者 Datetime 类型,推荐使用分区的日期字段。
能够使用的时间周期:
- SECOND
- MINUTE
- HOUR
- DAY
- WEEK
- MONTH
- QUARTER
- YEAR

7.二级索引

好处:不是为了“精确定位行”,而是为了“少读数据块”

目前在 ClickHouse 的官网上二级索引的功能在 v20.1.2.4 之前是被标注为实验性的,在
这个版本之后默认是开启的。

1)老版本使用二级索引前需要增加设置
是否允许使用实验性的二级索引(v20.1.2.4 开始,这个参数已被删除,默认开启)
set allow_experimental_data_skipping_indices=1;


2)创建测试表
create table t_order_mt2(
 id UInt32,
 sku_id String,
 total_amount Decimal(16,2),
 create_time Datetime,
INDEX a total_amount TYPE minmax GRANULARITY 5
) engine =MergeTree
partition by toYYYYMMDD(create_time)
primary key (id)
order by (id, sku_id);
其中 GRANULARITY N 是设定二级索引对于一级索引粒度的粒度。

insert into t_order_mt2 values
(101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
(102,'sku_002',2000.00,'2020-06-01 11:00:00'),
(102,'sku_004',2500.00,'2020-06-01 12:00:00'),
(102,'sku_002',2000.00,'2020-06-01 13:00:00'),
(102,'sku_002',12000.00,'2020-06-01 13:00:00'),
(102,'sku_002',600.00,'2020-06-02 12:00:00');

那么在使用下面语句进行测试,可以看出二级索引能够为非主键字段的查询发挥作用。
[atguigu@hadoop102 lib]$ clickhouse-client --send_logs_level=trace <<< 'select
* from t_order_mt2 where total_amount > toDecimal32(900., 2)';

8.副本搭建

副本的目的主要是保障数据的高可用性,即使一台 ClickHouse 节点宕机,那么也可以从
其他服务器获得相同的数据


配置步骤
(1)启动 zookeeper 集群

(2)在 hadoop102 的/etc/clickhouse-server/config.d 目录下创建一个名为 metrika.xml
的配置文件,内容如下:
<?xml version="1.0"?>
<yandex>
<zookeeper-servers>
 <node index="1">
 <host>hadoop102</host>
 <port>2181</port>
 </node>
 <node index="2">
 <host>hadoop103</host>
 <port>2181</port>
 </node>
 <node index="3">
 <host>hadoop104</host>
 <port>2181</port>
 </node>
</zookeeper-servers>
</yandex>3)在 hadoop102 的/etc/clickhouse-server/config.xml 中增加
<zookeeper incl="zookeeper-servers" optional="true" />
<include_from>/etc/clickhouse-server/config.d/metrika.xml</include_from>4)分发
sudo /home/atguigu/bin/xsync /etc/clickhouse-server

(5)在 hadoop102 和 hadoop103 上分别建表
副本只能同步数据,不能同步表结构,所以我们需要在每台机器上自己手动建表

create table t_order_rep2 (
 id UInt32,
 sku_id String,
 total_amount Decimal(16,2),
 create_time Datetime
) engine =ReplicatedMergeTree('/clickhouse/table/01/t_order_rep','rep_102')
 partition by toYYYYMMDD(create_time)
 primary key (id)
 order by (id,sku_id);

create table t_order_rep2 (
 id UInt32,
 sku_id String,
 total_amount Decimal(16,2),
 create_time Datetime
) engine =ReplicatedMergeTree('/clickhouse/table/01/t_order_rep','rep_103')
 partition by toYYYYMMDD(create_time)
 primary key (id)
 order by (id,sku_id);


参数解释
ReplicatedMergeTree 中,
第一个参数是分片的 zk_path 一般按照:/clickhouse/table/{shard}/{table_name} 的格式
写,如果只有一个分片就写 01 即可。
第二个参数是副本名称,相同的分片副本名称不能相同

9.分片与副本搭建

副本虽然能够提高数据的可用性,降低丢失风险,但是每台服务器实际上必须容纳全量
数据,对数据的横向扩容没有解决。
要解决数据水平切分的问题,需要引入分片的概念。通过分片把一份完整的数据进行切
分,不同的分片分布到不同的节点上,再通过 Distributed 表引擎把数据拼接起来一同使用。
Distributed 表引擎本身不存储数据,有点类似于 MyCat 之于 MySql,成为一种中间件,
通过分布式逻辑表来写入、分发、路由来操作多台节点不同分片的分布式数据。
注意:ClickHouse 的集群是表级别的,实际企业中,大部分做了高可用,但是没有用分
片,避免降低查询性能以及操作集群的复杂性。

(1)在 hadoop102 的/etc/clickhouse-server/config.d 目录下创建 metrika-shard.xml 文件
内容如下:

<?xml version="1.0"?>
<yandex>
    <remote_servers>
        <gmall_cluster> <!-- 集群名称-->
            <shard> <!--集群的第一个分片-->
                <internal_replication>true</internal_replication>
                <replica> <!--该分片的第一个副本-->
                    <host>hadoop102</host>
                    <port>9000</port>
                </replica>
                <replica> <!--该分片的第二个副本-->
                    <host>hadoop103</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard> <!--集群的第二个分片-->
                <internal_replication>true</internal_replication>
                <replica> <!--该分片的第一个副本-->
                    <host>hadoop104</host>
                    <port>9000</port>
                </replica>
            </shard>
        </gmall_cluster>
    </remote_servers>
    <zookeeper-servers>
        <node index="1">
            <host>hadoop102</host>
            <port>2181</port>
        </node>
        <node index="2">
            <host>hadoop103</host>
            <port>2181</port>
        </node>
        <node index="3">
            <host>hadoop104</host>
            <port>2181</port>
        </node>
    </zookeeper-servers>
    <macros>
        <shard>01</shard> <!--不同机器放的分片数不一样-->
        <replica>rep_1_1</replica> <!--不同机器放的副本数不一样-->
    </macros>
</yandex>2)在 hadoop102 的/etc/clickhouse-server/config.xml 中增加  
<zookeeper incl="zookeeper-servers" optional="true" /> 
<include_from>/etc/clickhouse-server/config.d/metrika.xml</include_from>

sudo /home/atguigu/bin/xsync /etc/clickhouse-server/config.xml

sudo /home/atguigu/bin/xsync /etc/clickhouse-server/config.d/metrika-shard.xml3)修改 103104 中 metrika-shard.xml 宏的配置

hadoop103
[atguigu@hadoop103 ~]$ sudo vim /etc/clickhouse-server/config.d/metrika-shard.xml
    <macros>
        <shard>01</shard> <!--不同机器放的分片数不一样-->
        <replica>rep_1_2</replica> <!--不同机器放的副本数不一样-->
    </macros>
    
hadoop104
[atguigu@hadoop104 ~]$ sudo vim /etc/clickhouse-server/config.d/metrika-shard.xml
    <macros>
        <shard>02</shard> <!--不同机器放的分片数不一样-->
        <replica>rep_2_1</replica> <!--不同机器放的副本数不一样-->
    </macros>

含义解释:
1)<remote_servers>:定义一个逻辑集群 gmall_cluster
2)分片 shard #1(有 2 个副本)
3)分片 shard #2(有 1 个副本)
第一份数据分片(shard1) 会存在两台机器上:hadoop102 和 hadoop103
这两台机器互为 副本:同一份分片数据复制两份,用于高可用和读扩展

第一份数据分片(shard2) 会存在一台机器上:hadoop104

4)internal_replication=true 的含义:
当你通过 Distributed 表往集群写数据时,如果目标 shard 有多个 replica:
true:通常只写入其中一个副本,由副本机制自己把数据同步到其它副本
false:可能会对 shard 的每个 replica 都写(更像“双写”),一般不推荐,容易带来重复/压力
简单理解:true 表示“副本复制由 ClickHouse 自己处理,我不手动双写副本”。

5)<zookeeper-servers>
<zookeeper-servers>
  <node index="1"><host>hadoop102</host><port>2181</port></node>
  <node index="2"><host>hadoop103</host><port>2181</port></node>
  <node index="3"><host>hadoop104</host><port>2181</port></node>
</zookeeper-servers>

含义:
ClickHouse 用这些 ZK 节点做 副本表(ReplicatedMergeTree) 的协调:
记录日志队列
选主/同步
记录每个副本的状态
没有 ZooKeeper,副本表就没法工作