首页 > 编程笔记 > 通用技能 阅读:17

ClickHouse是什么(超级详细)

商务智能(Business Intelligence,BI)系统的典型应用场景是多维分析,某些时候可以直接使用 OLAP 指代这类场景。一款优秀的 BI 类产品应该需要具备一站式、自服务且简单易用、实时应答、专业化和智能化的特征。

ClickHouse 具有 ROLAP、在线实时查询、完整的数据库管理系统、列式存储、不需要任何数据预处理、支持批量更新、拥有非常完善的 SQL 支持和函数、支持高可用、不依赖 Hadoop 复杂生态、开箱即用等许多特点,因此非常适用于 BI 领域。同时,ClickHouse 也广泛应用于电信、金融、信息安全、物联网等领域。

在采集数据的过程中,Click(点击)一次页面会产生一个 Event(事件)。这个过程可以理解为基于页面的点击事件(流),面向数据仓库进行 OLAP 分析,因此 ClickHouse 的全称是 Click Stream,Data WareHouse。

下图展示了 ClickHouse 名称的含义:


图 1 ClickHouse 名称的含义

ClickHouse基础内容

下面介绍 ClickHouse 中涉及的一些基本名词,以便于读者能够更好地理解 ClickHouse。

1) 表引擎

表引擎即表的类型,它是 ClickHouse 的核心概念,决定了:

2) 数据库

数据库是 ClickHouse 集群中的最高级别对象,内部包含表、列、视图、函数、数据类型等。

3) 表

表是数据的组织形式,由行和列构成。

ClickHouse 的表从数据分布上来看,可以分为本地表和分布式表两种类型;从存储引擎上来看,可以分为单机表和复制表两种类型。

4) 表分区

表中的数据可以按照指定的字段进行分区存储,每个分区在文件系统中以目录的形式存在。

常用的分区字段是时间字段,数据量大的表可以按照小时进行分区,数据量小的表可以按照天或者月进行分区。查询时使用分区字段作为 Where 语句条件,可以有效过滤掉大量非结果集数据。

5) 分片

在超大规模数据的处理场景下,单台服务器的存储、计算资源会成为性能瓶颈。为了进一步提高效率,ClickHouse 将海量数据分散存储到多台服务器上,每台服务器只存储和处理海量数据的一部分。在这种架构下,每台服务器称为一个分片。

一个分片本身就是 ClickHouse 的一个实例节点。分片的本质是提高查询效率,将一份全量的数据分成多份(片)能够降低单节点的数据扫描数量,提高查询性能。

6) 副本

为了在异常情况下保证数据的安全性和服务的高可用性,ClickHouse 提供了副本机制,将单台服务器的数据冗余地存储在2台或更多台服务器上。

7) 集群

在物理构成上,ClickHouse 集群是由多个 ClickHouse Server 实例组成的分布式数据库。这些 ClickHouse Server 根据购买规格的不同,可能包含 1 个或多个副本、1 个或多个分片。

在逻辑构成上,一个 ClickHouse 集群可以包含多个数据库对象。

ClickHouse数据表定义

ClickHouse 中有众多表引擎,不同的表引擎在底层数据存储上千差万别,在功能和性能上各有侧重。但实际生产中,使用最广泛的表引擎就是 MergeTree 引擎。

MergeTree 引擎是 ClickHouse 中最有特色,也是功能最强大的表引擎,实现了数据的分区、副本、突变、合并。我们在这里主要以使用 MergeTree 引擎为例,讲解数据表的组织和存储形式,以及内容。

数据表的目录组成可用如下树型结构表示:
clickhouse
└─ test_db
        ├─ test_table_a
        │      ├─ 20210224_0_1_1_2
        │      ├─ 20210224_3_3_0
        │      ├─ 20210225_0_1_2_3
        │      └─ 20210225_4_4_0
        └─ test_table_b
                ├─ 20210224_0_1_1_2
                ├─ 20210224_3_3_0
                ├─ 20210225_0_1_2_3
                └─ 20210225_4_4_0

在 ClickHouse 中,一个典型的数据表在文件系统中的目录结构如下图所示:


图 2 数据表的目录结构

数据库、数据表、分区都是按文件目录组织起来的,每个数据库会有对应的库目录,库中的每个表也会有各自对应的表目录。

每张表会包含若干个分区,这里的分区是一个逻辑概念,并不像数据表那样有目录与自己一一对应。在目录形式上,分区实际是一系列 Part(分区)的集合。每张表至少会有一个分区,如果不进行分区配置,则默认是一个全分区。

我们不再深入介绍 Part 的内容,对此有兴趣的读者可以自行查阅相关资料。

ClickHouse基本操作

1) 创建数据库

ClickHouse 可以通过指定表引擎的方式来创建数据库。在默认情况下,ClickHouse 使用的是原生的数据库引擎 Ordinary,当然也可以使用其他引擎,比如 MySQL 引擎。

数据库的创建有以下两种情况:
第一种情况,使用默认引擎创建数据库的语法结构如下:
CREATE database [if not exists] < database-name >;
语法结构中的 database-name 表示数据库名称。

例如,创建 myDB 数据库,代码如下:
CREATE database if not exists myDB;

第二种情况,使用其他引擎创建数据库的语法结构如下:
CREATE DATABASE [IF NOT EXISTS] < database-name > [ON CLUSTER< cluster-name >] [ENGINE = engine(...)]

这条语句会在 ClickHouse 中创建一个数据库,该数据库是其他引擎已存在的数据库的映射。我们可以对这个数据库执行 select 和 insert 命令,并把操作结果同步到指定引擎数据库。

例如,MySQL 中已存在一个名为 myMySQLDB 的数据库,我们使用以下代码在ClickHouse中创建数据库 myDB,并将该数据库映射到 myMySQLDB 上:
CREATE database if not exists myDB ENGINE = MySQL('127.0.0.1:3306',
'myMy SQLDB', 'root', '123456');

2) 删除数据库

删除数据库的语法结构与 SQL 语法结构基本相同,具体如下:
DROP database < database-name >;
例如,删除创建的 myDB 数据库,代码如下:
DROP database myDB;

3) 创建数据表

与创建数据库不同,创建数据表必须指定引擎,否则系统会报错,其语法结构如下:
CREATE table < table-name > (
    < field-name > type [COMMENT ...],
    ...
) ENGINE = (...)
[option]

例如,使用 MergeTree 引擎创建工厂商品数据表 product,代码如下:
CREATE table product (
    factory_goods_id UInt32 COMMENT ’工厂商品编号’,
    goods_name String COMMENT ’商品名称’,
    shop_id UInt32 COMMENT ’店铺编号’,
    shop_name String COMMENT ’店铺名称’,
    create_time DateTime COMMENT ’创建时间’,
    update_time DateTime COMMENT ’更新时间’
) ENGINE = MergeTree()
PRIMARY KEY factory_goods_id
ORDER BY factory_goods_id;

4) 删除数据表

删除数据表的语法结构与 SQL 语法结构基本相同,具体如下:
DROP table if exists < table-name >;
例如,删除创建的工厂商品数据表 product,代码如下:
DROP table if exists product;
如果 ClickHouse 是在集群上部署的,那么删除数据表应该带着集群的名称。例如,删除 factoryCluster 集群上的工厂商品数据表 product,代码如下:
DROP table product on CLUSTER elune;

5) 插入数据

插入数据的语法结构与SQL语法结构相似,二者不同之处主要体现在 ClickHouse 可以进行字段的批量插入。

ClickHouse 的语法结构如下:
INSERT into [database-name.]< table-name > [(< field-name >, …)]
VALUES (<value>, …), (<value>, …), …;
可以看到,VALUES 关键字后面可以跟多组数据,这说明 ClickHouse 的插入数据可以用于批量插入数据。

例如,在工厂商品数据表 product 中插入多条数据,代码如下:
INSERT into product(factory_goods_id, goods_name, shop_id, shop_name,
create_time, update_time)
values(1, ’商品1号’, 1, ’店铺1号’, '2023-07-06', '2023-07-07'),
      (2, ’商品2号’, 2, ’店铺2号’, '2023-07-06', '2023-07-07'),
      (3, ’商品3号’, 1, ’店铺3号’, '2023-07-06', '2023-07-07');

6) 查询数据

查询数据的语法结构与 SQL 语法结构基本相同,具体如下:
SELECT < field-name >, ...FROM < table-name > [where < condition >];
condition 表示查询条件。

例如,查询工厂商品数据表 product 的数据,代码如下:
SELECT factory_goods_id, goods_name, shop_id, shop_name, create_time,
update_time FROM product;
另外,在查询过程中,如分组、排序、聚合函数甚至表连接的语法结构都与 SQL 对应的语法结构相似,此处不再赘述。感兴趣的读者可以自行查阅相关资料。

7) 修改数据

修改数据的语法结构与 SQL 语法结构略有不同,可以简单地理解为 ClickHouse 将 SQL 中 DDL 的修改与 DML 的修改合二为一。

ClickHouse 修改数据的语法结构如下:
ALTER table < table_name > UPDATE field = value, … WHERE < condition >;

例如,将工厂商品数据表 prodcut 中 shop_id 为 2 的 shop_name 修改为店铺 3 号,代码如下:
ALTER table product UPDATE shop_name = ’店铺3号’ WHERE shop_id = 2;

8) 删除数据

删除数据的语法结构与 SQL 语法结构略有不同,可以简单地理解为 ClickHouse 将 SQL 中 DDL 的修改与 DML 的删除合二为一。

ClickHouse 的语法结构如下:
ALTER table < table_name > DELETE WHERE < condition >;
例如,删除工厂商品数据表 prodcut 中 factory_goods_id 为 3 的记录,代码如下:
ALTER table product DELETE WHERE factory_goods_id = 3;

需要注意的是,清空一张表的数据必须要加集群的名字,具体语法结构如下:
TRUNCATE table < table-name > on CLUSTER < cluster-name >;
例如,清空 factoryCluster 集群中的工厂商品数据表 prodcut 的数据,代码如下:
TRUNCATE table product on CLUSTER factoryCluster;

相关文章