安装ClickHouse数据库

OLAP和OLTP

数据库系统可以在广义上分为联机事务处理(Online Transaction Process,OLTP)和联机分析处理(Online Analyze Process,OLAP)两种面向不同领域的数据库,OLAP数据库也被称为数据仓库。从产品上看,有专门面向OLTP的数据库,例如MySQL、PostgreSQL、Oracle等,也有专门面向OLAP的数据库,例如Hive、Greenplum、HBase、ClickHouse等

OLAP OLTP
用途 数据仓库 事物数据库
业务目的 处理业务,如订单、合同等 业务支持决策
面向对象 业务处理人员 分析决策人员
主要工作负载 增、删、改 查询
数据容量 大,PB级 小,GB级
事务能力 弱(或无)
分析能力 弱,只能做简单的分析
数据来源 各业务数据库 各业务系统
设计原则 允许一定的冗余,基于数据仓库建模设计,为了更好的进行数据查询分析 基于三大范式进行数据库设计,所以查询时候会导致多表join关联查询,产生查询慢,不利于数据分析的问题

OLAP场景的关键特征

OLAP通常不直接产生数据,而是利用已有的数据进行建模分析。
1、绝大多数是读请求
2、数据以相当大的批次(> 1000行)更新,而不是单行更新;或者根本没有更新。
3、已添加到数据库的数据不能修改。
4、对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
5、宽表,即每个表包含着大量的列
6、查询相对较少(通常每台服务器每秒查询数百次或更少)
7、对于简单查询,允许延迟大约50毫秒
8、列中的数据相对较小:数字和短字符串(例如,每个URL 60个字节)
9、处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
10、事务不是必须的
11、对数据一致性要求低
12、每个查询有一个大表。除了他以外,其他的都很小。
13、查询结果明显小于源数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中

ClickHouse简介

ClickHouse是俄罗斯Yandex公司于2016年开源的一个用于联机分析(OLAP)的列式数据库管理系统。

ClickHouse可以在存储数据超过20万亿行的情况下,做到了90%的查询能够在1秒内返回。

官网地址:https://clickhouse.com/

安装

支持多种安装方式,这里使用docker的安装方式。更多安装方式参考:
https://clickhouse.com/docs/zh/getting-started/install

安装docker

安装clickhouse server

docker run -d -p 18123:8123 -p19000:9000 --name some-clickhouse-server --ulimit nofile=262144:262144 clickhouse/clickhouse-server

使用客户端连接

docker exec -it some-clickhouse-server clickhouse-client

使用 curl 连接

echo 'SELECT 1' | curl 'http://localhost:18123/' --data-binary @-

导入测试数据

测试数据来源:https://clickhouse.com/docs/zh/getting-started/example-datasets/menus

下载数据集

# 进入容器
docker exec -it some-clickhouse-server /bin/bash
# 进入home目录
cd /home
# 下载数据集
wget https://s3.amazonaws.com/menusdata.nypl.org/gzips/2021_08_01_07_01_17_data.tgz
# 解压数据集
tar xvf 2021_08_01_07_01_17_data.tgz
# 退出容器
exit;

创建测试数据库

# 进入容器
docker exec -it some-clickhouse-server clickhouse-client
# 创建数据库
CREATE DATABASE IF NOT EXISTS tutorial
# 查看有哪些数据库
SHOW DATABASES;

使用测试数据库

use tutorial;

创建表

CREATE TABLE dish \
( \
    id UInt32, \
    name String, \
    description String, \
    menus_appeared UInt32, \
    times_appeared Int32, \
    first_appeared UInt16, \
    last_appeared UInt16, \
    lowest_price Decimal64(3), \
    highest_price Decimal64(3) \
) ENGINE = MergeTree ORDER BY id;  \

CREATE TABLE menu \
( \
    id UInt32, \
    name String, \
    sponsor String, \
    event String, \
    venue String, \
    place String, \
    physical_description String, \
    occasion String, \
    notes String, \
    call_number String, \
    keywords String, \
    language String, \
    date String, \
    location String, \
    location_type String, \
    currency String, \
    currency_symbol String, \
    status String, \
    page_count UInt16, \
    dish_count UInt16 \
) ENGINE = MergeTree ORDER BY id;  \

CREATE TABLE menu_page \
( \
    id UInt32, \
    menu_id UInt32, \
    page_number UInt16, \
    image_id String, \
    full_height UInt16, \
    full_width UInt16, \
    uuid UUID \
) ENGINE = MergeTree ORDER BY id; \

CREATE TABLE menu_item \
( \
    id UInt32, \
    menu_page_id UInt32, \
    price Decimal64(3), \
    high_price Decimal64(3), \
    dish_id UInt32, \
    created_at DateTime, \
    updated_at DateTime, \
    xpos Float64, \
    ypos Float64 \
) ENGINE = MergeTree ORDER BY id;

查看有哪些表

SHOW TABLES

导入数据

# 进入容器
docker exec -it some-clickhouse-server /bin/bash
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO tutorial.dish FORMAT CSVWithNames" < /home/Dish.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO tutorial.menu FORMAT CSVWithNames" < /home/Menu.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --query "INSERT INTO tutorial.menu_page FORMAT CSVWithNames" < /home/MenuPage.csv
clickhouse-client --format_csv_allow_single_quotes 0 --input_format_null_as_default 0 --date_time_input_format best_effort --query "INSERT INTO tutorial.menu_item FORMAT CSVWithNames" < /home/MenuItem.csv

非规范化数据

数据以 [规范化形式] 在多个表格中呈现。这意味着如果你想进行如查询菜单项中的菜名这类的查询,则必须执行 JOIN。在典型的分析任务中,预先处理联接的数据以避免每次都执行“联接”会更有效率。这中操作被称为“非规范化”数据。

创建一个表“menu_item_denorm”,其中将包含所有联接在一起的数据:

CREATE TABLE menu_item_denorm
ENGINE = MergeTree ORDER BY (dish_name, created_at)
AS SELECT
    price,
    high_price,
    created_at,
    updated_at,
    xpos,
    ypos,
    dish.id AS dish_id,
    dish.name AS dish_name,
    dish.description AS dish_description,
    dish.menus_appeared AS dish_menus_appeared,
    dish.times_appeared AS dish_times_appeared,
    dish.first_appeared AS dish_first_appeared,
    dish.last_appeared AS dish_last_appeared,
    dish.lowest_price AS dish_lowest_price,
    dish.highest_price AS dish_highest_price,
    menu.id AS menu_id,
    menu.name AS menu_name,
    menu.sponsor AS menu_sponsor,
    menu.event AS menu_event,
    menu.venue AS menu_venue,
    menu.place AS menu_place,
    menu.physical_description AS menu_physical_description,
    menu.occasion AS menu_occasion,
    menu.notes AS menu_notes,
    menu.call_number AS menu_call_number,
    menu.keywords AS menu_keywords,
    menu.language AS menu_language,
    menu.date AS menu_date,
    menu.location AS menu_location,
    menu.location_type AS menu_location_type,
    menu.currency AS menu_currency,
    menu.currency_symbol AS menu_currency_symbol,
    menu.status AS menu_status,
    menu.page_count AS menu_page_count,
    menu.dish_count AS menu_dish_count
FROM menu_item
    JOIN dish ON menu_item.dish_id = dish.id
    JOIN menu_page ON menu_item.menu_page_id = menu_page.id
    JOIN menu ON menu_page.menu_id = menu.id;

验证数据

SELECT count() FROM menu_item_denorm;

运行一些查询

菜品的平均历史价格

SELECT
    round(toUInt32OrZero(extract(menu_date, '^\\d{4}')), -1) AS d,
    count(),
    round(avg(price), 2),
    bar(avg(price), 0, 100, 100)
FROM menu_item_denorm
WHERE (menu_currency = 'Dollars') AND (d > 0) AND (d < 2022)
GROUP BY d
ORDER BY d ASC;

发表评论

邮箱地址不会被公开。 必填项已用*标注