快速上手 ClickHouse

2021-10-18 10:24:52 浏览数 (2)

本篇来自数月前对外分享的文稿整理,并进行了一些扩展。

希望通过简单的方式,来介绍新手如何一步一步上手 ClickHouse,如果你有潜在的数据分析的需求,但是不知道从哪里开始,那么希望本文能够帮助到你。

写在前面

关于 ClickHouse 在追求性能的场景下的溢美之词,我觉得没有必要再重复了。以过往经验来看,你可以使用极其低的成本来完成以往 RDBMS(比如MySQL)做不到的准实时级别的数据分析,也可以用它来做远程多个数据库实例的数据迁移或者归档存储。

感谢两年前一位好朋友对我进行的技术选型推荐,使用 ClickHouse 可以简化非常多的不必要的基础设施搭建和维护。我们曾搭建过一台比较奢华的机器(256核心512GB内存)来进行准实时的数据分析(花费万分之几秒从海量数据中查结果),以及支持每秒落地几十万条以上数据,而丝毫不影响服务器查询性能;也曾实践过从两千块的 NUC 上跑边缘计算任务,相对快速的拿到需要分析的结果(花费千分之一到百分之一秒),以及在16核心64GB内存的普通笔记本上,跑超过十亿数据集的复杂计算的尝试(分钟级)。

之前使用过的“豪华”配置之前使用过的“豪华”配置

所以,如果你有以下需求,ClickHouse 可能也会非常适合你:

  • 快速分析一些离线数据,做数据计算、聚合、筛选。
  • 有大量读取需求,并且针对原始数据修改的需求非常少,如果存在这类需求,可以接受“追加数据”配合“版本过滤”的方式处理。
  • 数据字段比较丰富,数据存在非常多“列”。
  • 业务并发需求不高,查询者(消费者)只有几个或者一两百个以下。

先来聊聊硬件选择。

硬件选择策略

会考虑选择 ClickHouse 的同学,一般应该是遇到了当前业务,到了需要或者不得不“考虑效率”的时刻。

一般情况,很少有需要直接把 ClickHouse 返回数据作为同步结果直接返回给调用方的场景,勤俭节约的程序员们一般都会使用异步模式,所以在极少并发的情况下,我们对于 ClickHouse 的硬件要求也就越来越低了: 亿级别以下的数据,最低只要 4核心16GB 的虚拟机也能轻松搞定;而亿级别到百亿级别的数据,只要你能搞定32~64G内存,计算出来的时间也只几乎只和你设备的核心数数量、CPU缓存大小是多少有关而已

所以,在考虑使用 ClickHouse 的时候,如果你是用来做一个快速或者相对快速的“离线”数据分析,那么优先需要考虑的是你的数据量有多大,以及需要满足快速计算的内存门槛下限是否足够,接着才是考虑你需要多快的拿到计算结果,尽量在成本预算之内,优先选择拥有更多的核心数的 CPU、以及更大的 CPU 缓存 。至于 Cluster 模式,除非你需要提供实时接口,对于服务可用性有极高依赖和要求,有特别大的数据写入压力,不然默认情况是不需要配置的。当然,如果你有需求配置 Cluster,不推荐使用默认的分布式模式,因为数据并非完整镜像,而是均匀分布在每一个节点,如果某一个节点跪掉,你将“实时”损失 N 分之 1 的数据,导致最终计算结果不能说不准确,只能说压根可能是错的。官网为此推出了一个“Replicated”的数据库引擎,这个数据库引擎基于 Atomic 引擎,借助 ZooKeeper 进行完整的数据复制,虽然目前还处于实验阶段,但是总比“丢数据”强吧。

除此之外,还有一个因素会极大的影响 ClickHouse 帮助我们拿到计算结果的时间,就是存储介质,这里推荐使用 SSD 作为存储介质,如果你是用于小样本分析,甚至可以使用 TB 规格、便宜的民用存储。如果追求极致成本,甚至可以参考我之前的内容《廉价的家用工作站方案:前篇》、《NUC 折腾笔记 - 储存能力测试》,如果你是进行高频次、海量数据的计算,有比较大的存储量下限要求和可预期的大容量数据增长,考虑到成本和更高的数据存储可靠性,Raid 50 模式的机械磁盘会更适合你。

当然,如果你目前啥都没有,只是用于学习,本地起一个 Docker 容器,也能开始学习之旅,以及百万到千万级别的数据计算和分析。

软件环境选择

我目前所有的机器都运行在 Ubuntu 容器环境,为什么这么选择呢,因为“Ubuntu 是容器世界里的一等公民”,本文考虑到快速上手,也同样选择使用套环境。

当然,如果你选择裸机直接安装 ClickHouse,使用更稳定的 Debian 也是个不错的选择,至于 CentOS ,时至今日,真的是没有推荐的理由和必要了(企业付费购买 RHEL 是另外一个话题)。

在容器环境内跑 ClickHouse 会损失比较多的“转换”性能,在存储和网络转发上都会存在一定的体现,所以实际生产环境能够裸机安装的,请脱离容器使用。

如果你已经安装好了 Docker环境,那么我们可以继续下一个章节啦。如果你还不熟悉如何安装 Docker,可以参考本站知识地图中的关于容器安装的内容,自行了解学习。

前置准备:测试使用的数据集

为了熟悉和了解基础语法和进行 ClickHouse 高性能体验,我们可以先使用官方提供的 Yandex.Metrica Data 来进行试验。(更多的性能测试,可以从官方仓库的 测试数据集 中了解)

  1. https://datasets.clickhouse.tech/hits/partitions/hits_v1.tar
  2. https://datasets.clickhouse.tech/visits/partitions/visits_v1.tar

此外,为了演示如何在不纠结数据类型转换的情况下,快速完成数据导入,我们还需要使用一个传统类型的数据库的数据集进行操作,这里选择网友开源项目中使用的“人人影视”数据库(MySQL) https://yyets.dmesg.app/database

数据下载完毕之后,我们需要先对数据进行解压缩。

代码语言:txt复制
mkdir data
tar xvf hits_v1.tar -C data
tar xvf visits_v1.tar -C data

通过 du 命令可以看到使用的数据实际使用了 1.7GB空间,顺便提一下,这些数据如果存储在 MySQL 中,存储空间可能会膨胀 3~5倍以上。

代码语言:txt复制
du -hs data
1.7G	data

数据解压完毕,就可以开始准备对 ClickHouse 的容器运行配置了。

前置准备:准备 ClickHouse 运行配置

代码语言:txt复制
version: "2"

services:

  server:
    image: yandex/clickhouse-server:21.9.4.35
    container_name: clickhouse
    expose:
      - 9000
      - 8123
      - 9009
    ulimits:
      nproc: 65535
      nofile:
        soft: 262144
        hard: 262144
    environment:
      - TZ=Asia/Shanghai
      # - CLICKHOUSE_USER=root
      # - CLICKHOUSE_PASSWORD=xmnzdwH5
    volumes:
      - ./data:/var/lib/clickhouse
      # 按需使用
      # - ./config.xml:/etc/clickhouse-server/config.xml
      # - ./users.xml:/etc/clickhouse-server/users.xml

将上面的配置保存为 docker-compose.yml,并使用 docker-compose up -d 启动 ClickHouse,以备稍后使用。

额外说一下,ClickHouse 的版本更新很快,建议升级的时候先做一些小样本测试,测试常用场景是否正常,再进行版本更新替换。

ClickHouse 初体验

ClickHouse 使用的 SQL 语法相比较 MySQL 等数据库会宽松许多,类比的话,就像是之前写 Java 的选手一下子步入了 Python 和 JavaScript 的世界。

因为使用容器启动 ClickHouse,所以我们可以通过 docker exec 命令进入 ClickHouse 的交互式终端。

代码语言:txt复制
docker exec -it clickhouse clickhouse-client

进入终端后,先来看看有哪些“数据库”和数据表:

代码语言:txt复制
# 查看数据库
cc1b062138da :) show databases

SHOW DATABASES

Query id: efaa1c51-e112-43d6-b803-1e6dd86ad43b

┌─name─────┐
│ datasets │
│ default  │
│ system   │
└──────────┘

3 rows in set. Elapsed: 0.003 sec. 

# 切换数据库
cc1b062138da :) use datasets

USE datasets

Query id: b10ff8f3-0743-42f4-9ee1-663b9a2c4955

Ok.

0 rows in set. Elapsed: 0.002 sec. 

# 查看数据表
cc1b062138da :) show tables

SHOW TABLES

Query id: c6eb8203-6ea2-4576-9bb7-74ad4e1c7de9

┌─name──────┐
│ hits_v1   │
│ visits_v1 │
└───────────┘

2 rows in set. Elapsed: 0.005 sec. 

上面的结果中的 datasets 就是我们导入的数据集。ClickHouse 对于数据存放比较“佛系”,如果你查看本地目录可以看到上面的数据和 data/datasets 目录保持一致,实际操作使用的时候,只要把 data 目录打个压缩包就能完成数据备份了,是不是很简单。

代码语言:txt复制
 tree -L 3 data/data/datasets 
data/data/datasets
├── hits_v1
│   ├── 201403_10_18_2
│   │   ├── AdvEngineID.bin
│   │   ├── AdvEngineID.mrk
│   │   ├── Age.bin
│   │   ├── Age.mrk
│   │   ├── UserID.bin
│   │   ├── UserID.mrk
...
│   │   ├── WatchID.bin
│   │   ├── WatchID.mrk
│   │   ├── YCLID.bin
│   │   ├── YCLID.mrk
│   │   ├── checksums.txt
│   │   ├── columns.txt
│   │   ├── count.txt
│   │   ├── minmax_EventDate.idx
│   │   ├── partition.dat
│   │   └── primary.idx
│   ├── detached
│   └── format_version.txt
└── visits_v1
    ├── 20140317_20140323_3_4_1
    │   ├── AdvEngineID.bin
    │   ├── AdvEngineID.mrk
    │   ├── Age.bin
    │   ├── Age.mrk
    │   ├── Attendance.bin
    │   ├── Attendance.mrk
...
    │   ├── ClickBannerID.bin
    │   ├── ClickBannerID.mrk
    │   ├── ClickClientIP.bin
    │   ├── ClickClientIP.mrk
    │   ├── YCLID.bin
    │   ├── YCLID.mrk
    │   ├── checksums.txt
    │   ├── columns.txt
    │   └── primary.idx
    ├── detached
    └── format_version.txt

6 directories, 675 files

为了后续敲的命令能简单些,我们针对数据表先进行一个重命名操作。

代码语言:txt复制
# 分别去掉两张表的版本后缀

cc1b062138da :) rename table hits_v1 to hits

RENAME TABLE hits_v1 TO hits

Query id: dba1405a-1836-4d5a-af23-3ce0f5b31d41

Ok.

0 rows in set. Elapsed: 0.014 sec. 



cc1b062138da :) rename table visits_v1 to visits

RENAME TABLE visits_v1 TO visits

Query id: 9ffc039c-86c3-42a9-91a6-3ed165254e0b

Ok.

0 rows in set. Elapsed: 0.012 sec. 


# 再次查看数据表
cc1b062138da :) show tables

SHOW TABLES

Query id: da91fb7c-5224-4c7f-9a6c-ce4cf37f9fa8

┌─name───┐
│ hits   │
│ visits │
└────────┘

2 rows in set. Elapsed: 0.004 sec. 

将数据表重命名之后,接下来,来看看这两张表里到底有多少数据。

代码语言:txt复制
SELECT
    hits,
    visits
FROM 
(
    SELECT count() AS hits
    FROM hits
) AS table_hits
, 
(
    SELECT count() AS visits
    FROM visits
) AS table_visits

可以看到两张表数据量都不大,百万到千万级别。

代码语言:txt复制
┌────hits─┬──visits─┐
│ 8873898 │ 1676861 │
└─────────┴─────────┘

1 rows in set. Elapsed: 0.005 sec. 

接着我们来查看一下两张表的表结构,可以看到两张表,分别有133个、181个列,是“一般意义上的”宽表,非常适合进行分析使用。

代码语言:txt复制
desc hits


cc1b062138da :) desc hits
:-] 
:-] 

DESCRIBE TABLE hits

Query id: b8d8b650-2395-4207-b2ce-4200dc9c0fce

┌─name───────────────────────┬─type────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ WatchID                    │ UInt64          │              │                    │         │                  │                │
│ JavaEnable                 │ UInt8           │              │                    │         │                  │                │
│ Title                      │ String          │              │                    │         │                  │                │
│ GoodEvent                  │ Int16           │              │                    │         │                  │                │
│ EventTime                  │ DateTime        │              │                    │         │                  │                │
│ EventDate                  │ Date            │              │                    │         │                  │                │
│ CounterID                  │ UInt32          │              │                    │         │                  │                │
│ ClientIP                   │ UInt32          │              │                    │         │                  │                │
│ ClientIP6                  │ FixedString(16) │              │                    │         │                  │                │
│ RegionID                   │ UInt32          │              │                    │         │                  │                │
│ UserID                     │ UInt64          │              │                    │         │                  │                │
│ CounterClass               │ Int8            │              │                    │         │                  │                │
│ OS                         │ UInt8           │              │                    │         │                  │                │
│ UserAgent                  │ UInt8           │              │                    │         │                  │                │
│ URL                        │ String          │              │                    │         │                  │                │
│ Referer                    │ String          │              │                    │         │                  │                │
│ URLDomain                  │ String          │              │                    │         │                  │                │
│ RefererDomain              │ String          │              │                    │         │                  │                │
│ Refresh                    │ UInt8           │              │                    │         │                  │                │
│ IsRobot                    │ UInt8           │              │                    │         │                  │                │
│ RefererCategories          │ Array(UInt16)   │              │                    │         │                  │                │
│ URLCategories              │ Array(UInt16)   │              │                    │         │                  │                │
│ URLRegions                 │ Array(UInt32)   │              │                    │         │                  │                │
│ RefererRegions             │ Array(UInt32)   │              │                    │         │                  │                │
│ ResolutionWidth            │ UInt16          │              │                    │         │                  │                │
│ ResolutionHeight           │ UInt16          │              │                    │         │                  │                │
│ ResolutionDepth            │ UInt8           │              │                    │         │                  │                │
│ FlashMajor                 │ UInt8           │              │                    │         │                  │                │
│ FlashMinor                 │ UInt8           │              │                    │         │                  │                │
│ FlashMinor2                │ String          │              │                    │         │                  │                │
│ NetMajor                   │ UInt8           │              │                    │         │                  │                │
│ NetMinor                   │ UInt8           │              │                    │         │                  │                │
│ UserAgentMajor             │ UInt16          │              │                    │         │                  │                │
│ UserAgentMinor             │ FixedString(2)  │              │                    │         │                  │                │
│ CookieEnable               │ UInt8           │              │                    │         │                  │                │
│ JavascriptEnable           │ UInt8           │              │                    │         │                  │                │
│ IsMobile                   │ UInt8           │              │                    │         │                  │                │
│ MobilePhone                │ UInt8           │              │                    │         │                  │                │
│ MobilePhoneModel           │ String          │              │                    │         │                  │                │
│ Params                     │ String          │              │                    │         │                  │                │
│ IPNetworkID                │ UInt32          │              │                    │         │                  │                │
│ TraficSourceID             │ Int8            │              │                    │         │                  │                │
│ SearchEngineID             │ UInt16          │              │                    │         │                  │                │
│ SearchPhrase               │ String          │              │                    │         │                  │                │
│ AdvEngineID                │ UInt8           │              │                    │         │                  │                │
│ IsArtifical                │ UInt8           │              │                    │         │                  │                │
│ WindowClientWidth          │ UInt16          │              │                    │         │                  │                │
│ WindowClientHeight         │ UInt16          │              │                    │         │                  │                │
│ ClientTimeZone             │ Int16           │              │                    │         │                  │                │
│ ClientEventTime            │ DateTime        │              │                    │         │                  │                │
│ SilverlightVersion1        │ UInt8           │              │                    │         │                  │                │
│ SilverlightVersion2        │ UInt8           │              │                    │         │                  │                │
│ SilverlightVersion3        │ UInt32          │              │                    │         │                  │                │
│ SilverlightVersion4        │ UInt16          │              │                    │         │                  │                │
│ PageCharset                │ String          │              │                    │         │                  │                │
│ CodeVersion                │ UInt32          │              │                    │         │                  │                │
│ IsLink                     │ UInt8           │              │                    │         │                  │                │
│ IsDownload                 │ UInt8           │              │                    │         │                  │                │
│ IsNotBounce                │ UInt8           │              │                    │         │                  │                │
│ FUniqID                    │ UInt64          │              │                    │         │                  │                │
│ HID                        │ UInt32          │              │                    │         │                  │                │
│ IsOldCounter               │ UInt8           │              │                    │         │                  │                │
│ IsEvent                    │ UInt8           │              │                    │         │                  │                │
│ IsParameter                │ UInt8           │              │                    │         │                  │                │
│ DontCountHits              │ UInt8           │              │                    │         │                  │                │
│ WithHash                   │ UInt8           │              │                    │         │                  │                │
│ HitColor                   │ FixedString(1)  │              │                    │         │                  │                │
│ UTCEventTime               │ DateTime        │              │                    │         │                  │                │
│ Age                        │ UInt8           │              │                    │         │                  │                │
│ Sex                        │ UInt8           │              │                    │         │                  │                │
│ Income                     │ UInt8           │              │                    │         │                  │                │
│ Interests                  │ UInt16          │              │                    │         │                  │                │
│ Robotness                  │ UInt8           │              │                    │         │                  │                │
│ GeneralInterests           │ Array(UInt16)   │              │                    │         │                  │                │
│ RemoteIP                   │ UInt32          │              │                    │         │                  │                │
│ RemoteIP6                  │ FixedString(16) │              │                    │         │                  │                │
│ WindowName                 │ Int32           │              │                    │         │                  │                │
│ OpenerName                 │ Int32           │              │                    │         │                  │                │
│ HistoryLength              │ Int16           │              │                    │         │                  │                │
│ BrowserLanguage            │ FixedString(2)  │              │                    │         │                  │                │
│ BrowserCountry             │ FixedString(2)  │              │                    │         │                  │                │
│ SocialNetwork              │ String          │              │                    │         │                  │                │
│ SocialAction               │ String          │              │                    │         │                  │                │
│ HTTPError                  │ UInt16          │              │                    │         │                  │                │
│ SendTiming                 │ Int32           │              │                    │         │                  │                │
│ DNSTiming                  │ Int32           │              │                    │         │                  │                │
│ ConnectTiming              │ Int32           │              │                    │         │                  │                │
│ ResponseStartTiming        │ Int32           │              │                    │         │                  │                │
│ ResponseEndTiming          │ Int32           │              │                    │         │                  │                │
│ FetchTiming                │ Int32           │              │                    │         │                  │                │
│ RedirectTiming             │ Int32           │              │                    │         │                  │                │
│ DOMInteractiveTiming       │ Int32           │              │                    │         │                  │                │
│ DOMContentLoadedTiming     │ Int32           │              │                    │         │                  │                │
│ DOMCompleteTiming          │ Int32           │              │                    │         │                  │                │
│ LoadEventStartTiming       │ Int32           │              │                    │         │                  │                │
│ LoadEventEndTiming         │ Int32           │              │                    │         │                  │                │
│ NSToDOMContentLoadedTiming │ Int32           │              │                    │         │                  │                │
│ FirstPaintTiming           │ Int32           │              │                    │         │                  │                │
│ RedirectCount              │ Int8            │              │                    │         │                  │                │
│ SocialSourceNetworkID      │ UInt8           │              │                    │         │                  │                │
│ SocialSourcePage           │ String          │              │                    │         │                  │                │
│ ParamPrice                 │ Int64           │              │                    │         │                  │                │
│ ParamOrderID               │ String          │              │                    │         │                  │                │
│ ParamCurrency              │ FixedString(3)  │              │                    │         │                  │                │
│ ParamCurrencyID            │ UInt16          │              │                    │         │                  │                │
│ GoalsReached               │ Array(UInt32)   │              │                    │         │                  │                │
│ OpenstatServiceName        │ String          │              │                    │         │                  │                │
│ OpenstatCampaignID         │ String          │              │                    │         │                  │                │
│ OpenstatAdID               │ String          │              │                    │         │                  │                │
│ OpenstatSourceID           │ String          │              │                    │         │                  │                │
│ UTMSource                  │ String          │              │                    │         │                  │                │
│ UTMMedium                  │ String          │              │                    │         │                  │                │
│ UTMCampaign                │ String          │              │                    │         │                  │                │
│ UTMContent                 │ String          │              │                    │         │                  │                │
│ UTMTerm                    │ String          │              │                    │         │                  │                │
│ FromTag                    │ String          │              │                    │         │                  │                │
│ HasGCLID                   │ UInt8           │              │                    │         │                  │                │
│ RefererHash                │ UInt64          │              │                    │         │                  │                │
│ URLHash                    │ UInt64          │              │                    │         │                  │                │
│ CLID                       │ UInt32          │              │                    │         │                  │                │
│ YCLID                      │ UInt64          │              │                    │         │                  │                │
│ ShareService               │ String          │              │                    │         │                  │                │
│ ShareURL                   │ String          │              │                    │         │                  │                │
│ ShareTitle                 │ String          │              │                    │         │                  │                │
│ ParsedParams.Key1          │ Array(String)   │              │                    │         │                  │                │
│ ParsedParams.Key2          │ Array(String)   │              │                    │         │                  │                │
│ ParsedParams.Key3          │ Array(String)   │              │                    │         │                  │                │
│ ParsedParams.Key4          │ Array(String)   │              │                    │         │                  │                │
│ ParsedParams.Key5          │ Array(String)   │              │                    │         │                  │                │
│ ParsedParams.ValueDouble   │ Array(Float64)  │              │                    │         │                  │                │
│ IslandID                   │ FixedString(16) │              │                    │         │                  │                │
│ RequestNum                 │ UInt32          │              │                    │         │                  │                │
│ RequestTry                 │ UInt8           │              │                    │         │                  │                │
└────────────────────────────┴─────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

133 rows in set. Elapsed: 0.003 sec. 

cc1b062138da :) 

再来看看另外一张表:

文章字数超过编辑器5万字限制,需要继续阅读的同学,可以查阅文末底部的链接。


如果你觉得内容还算实用,欢迎点赞分享给你的朋友,在此谢过。


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2021年10月16日

统计字数: 33858字

阅读时间: 68分钟阅读

本文链接: https://soulteary.com/2021/10/16/get-started-quickly-with-clickhouse.html

0 人点赞