ClickHouse的原理及使用,

1、前言

一款MPP查询分析型数据库——ClickHouse。它是一个开源的,面向列的分析数据库,由Yandex为OLAP和大数据用例创建。ClickHouse对实时查询处理的支持使其适用于需要亚秒级分析结果的应用程序。ClickHouse的查询语言是SQL的一种方言,它支持强大的声明性查询功能,同时为最终用户提供熟悉度和较小的学习曲线。

它可以替代Elasticserach做深度聚合需求,性能表现不错,在数据量千万级亿级表现很好,且资源消耗相比之前降低不少,同样的服务器资源可以承担更多的业务需求。

2、ClickHouse 概述

1.1 什么是ClickHouse

ClickHouse 是俄罗斯的 Yandex 于2016年开源的列式存储数据库(DBMS),主要用于在线分析处理查询(OLAP),能够使用SQL 查询实时生成分析数据报告。

1.2 什么是列式存储

以下面的表为例:

IdNameAge
1张三18
2李四22
3王五34

采用行式存储时,数据在磁盘上的组织结构为:

好处是想查某个人所有的属性时,可以通过一次磁盘查找加顺序读取就可以。但是当想查所有人的年龄时,需要不停的查找,或者全表扫描才行,遍历的很多数据都是不需要的。

而采用列式存储时,数据在磁盘上的组织结构为:

这时想查所有人的年龄只需把年龄那一列拿出来就可以了。

1.3 安装前的准备

1.3.1 CentOS 取消打开文件数限制

在/etc/security/limits.conf、 /etc/security/limits.d/90-nproc.conf 这2个文件的末尾加入一下内容:

vi /etc/security/limits.conf
在文件末尾添加:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

vi /etc/security/limits.d/90-nproc.conf
在文件末尾添加:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

重启服务器之后生效,用ulimit -n 或者 ulimit -a 查看设置结果

ulimit -n

1.3.2 CentOS 取消SELINUX

SELINUX 是 CentOS 类似于windows 下的安全360,修改 /etc/selinux/config 中的 SELINUX=disabled 后重启

vi /etc/selinux/config
SELINUX=disabled

1.3.3 关闭防火墙

service iptables stop
service ip6tables stop

1.3.4 安装依赖

yum install -y libtool
yum install -y *unixODBC*
yum search libicu
yum install libicu.x86_64

2、安装

2.1 网址

官网:https://clickhouse.yandex/

下载地址:http://repo.red-soft.biz/repos/clickhouse/stable/el7/

2.2 单机模式

上传5个文件到 mkdir /usr/local/clickhouse

clickhouse-client-1.1.54236-4.el7.x86_64.rpm    09-Jun-2017 11:02   3.0K     
clickhouse-compressor-1.1.54236-4.el7.x86_64.rpm    09-Jun-2017 11:02   880K     
clickhouse-debuginfo-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02   8.6M     
clickhouse-server-1.1.54236-4.el7.x86_64.rpm    09-Jun-2017 11:02   32M  
clickhouse-server-common-1.1.54236-4.el7.x86_64.rpm 09-Jun-2017 11:02   8.0K

2.2.2 分别安装这5个rpm 文件

rpm -ivh /usr/local/clickhouse/*.rpm

2.2.3 启动 ClickServer

前台启动:

clickhouse-server --config-file=/etc/clickhouse-server/config.xml

查看启动后的进程:ps -aux | grep click

后台启动:

nohup clickhouse-server --config-file=/etc/clickhouse-server/config.xml >null 2>&1 &

2.2.4 使用 client 连接server

clickhouse-client

2.3 分布式集群安装

2.3.1 在node-02、node-03 上面执行之前的所有步骤

2.3.2 三台机器修改配置文件 vi /etc/clickhouse-server/config.xml

<listen_host>0.0.0.0</listen_host>
    <!-- <listen_host>::1</listen_host> -->
    <!-- <listen_host>127.0.0.1</listen_host> -->

将刚刚修改好的配置分发到三台机器上去: ync.sh /etc/clickhouse-server/config.xml

2.3.3 在三台机器的etc 目录下新建 metrika.xml 文件

vi /etc/metrika.xml
添加如下内容:

<yandex>
<clickhouse_remote_servers>
<perftest_3shards_1replicas>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>node-01</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<internal_replication>true</internal_replication>
<host>node-02</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>node-03</host>
<port>9000</port>
</replica>
</shard>
</perftest_3shards_1replicas>
</clickhouse_remote_servers>

<!--zookeeper相关配置-->
<zookeeper-servers>
<node index="1">
<host>node-01</host>
<port>2181</port>
</node>
<node index="2">
<host>node-02</host>
<port>2181</port>
</node>
<node index="3">
<host>node-03</host>
<port>2181</port>
</node>
</zookeeper-servers>

<macros>
<replica>node-01</replica>
</macros>

<networks>
<ip>::/0</ip>
</networks>

<clickhouse_compression>
<case>
<min_part_size>10000000000</min_part_size>
<min_part_size_ratio>0.01</min_part_size_ratio>
<method>lz4</method>
</case>
</clickhouse_compression>

</yandex>

注意:下面标红的地方需要根据机器不同去修改,node-02就是修改成node-02, node-03就是修改成node-03

node-01

3.3.4 三台机器启 ClickServer

首先在三台机器开启Zookeeper

前台启动:

clickhouse-server --config-file=/etc/clickhouse-server/config.xml

查看启动后的进程:ps -aux | grep click

后台启动:

nohup clickhouse-server --config-file=/etc/clickhouse-server/config.xml >null 2>&1 &

集群搭建成功,进入clickhouse-client 客户端:

这里补充ClickHouse与Elasticsearch一样,都采用列式存储结构,都支持副本分片,不同的是ClickHouse底层有一些独特的实现,如下:

  • MergeTree 合并树表引擎,提供了数据分区、一级索引、二级索引。
  • Vector Engine 向量引擎,数据不仅仅按列存储,同时还按向量(列的一部分)进行处理,这样可以更加高效地使用CPU。

3、数据类型

3.1 整型

固定长度的整型,包括有符号整型或无符号整型。Clickhouse 对大小写敏感。整型范围(-2^(n-1) ~ 2^(n-1) - 1):

Int8 −128:127
Int16 −32768:32767
Int32 −2147483648:2147483647
Int64 −9223372036854775808:9223372036854775807

无符号整型范围(0 ~ 2^n -1)

UInt8 0:255
UInt16 0:65535
UInt32 0:4294967295
UInt64 0:18446744073709551615

3.2 浮点型

Float32 - float
Float64 - double

建议尽可能以整型形式存储数据。例如,将固定精度的数字转换为整数值,如果间用毫秒为单位表示,因为浮点型进行计算时可能引起四舍五入的误差,比如1-0.9。

与标准SQL 相比,ClickHouse 支持以下类别的浮点数:Inf - 正无穷  1/0-Inf - 负无穷 NaN - 非数字:

3.3 布尔型

没有单独的类型来存储布尔值。可以使用 UInt8 类型,取值限制为 0 或 1 。

3.4 字符串

1)String

字符串可以任意长度的。它可以包含任意的字节集,包含空字节。

2) FixedString(N)

固定长度N 的字符串,N 必须是严格的正自然数。当服务端读取长度小于N的字符串时候,通过在字符串末尾添加空字节来达到N 字节长度。当服务端读取长度大于 N 的字符串时候,将返回错误消息。与String 相比,极少会使用FixedString,因为使用起来不是很方便。

3.5 枚举类型

ClickHouse 支持枚举类型,这是一种在定义常量时经常会使用的数据类型。ClickHouse 提供了Enum8 和Enum16 两种枚举类型,它们除了取值范围不同之外,别无二致。枚举固定使用(String:Int)Key/Value 键值对的形式定义数据,所以Enum8 和Enum16分别会对应(String:Int8)和(String:Int16)

用法演示:

create table enum(enum Enum8('hello'=0, 'enum'=1))engine=TinyLog
-- 枚举数据类型
CREATE TABLE test_enum(id Int8, color Enum8('red'=1, 'green'=2, 'blue'=3)) engine=Memory;
insert into test_enum values(1,'red'),(2,'red'),(3,'green');
-- 也可以使用这种方式进行插入数据:
insert into test_enum values(4,3);
insert into test_enum values(5,'pink'); -- 没有声明的值是不能插入

select id, toInt32(color) from test_enum;
-- 节省存储空间,提升处理效率;底层存储Int类型,占用空间最小

3.6 数组

Array(T):由T 类型元素组成的数组。T 可以是任意类型,包含数组类型。但不推荐使用多维数组,ClickHouse 对多维数组的支持有限。例如,不能在MergeTree 表中存储多维数组。可以使用 array 函数来创建数组:array(T)也可以使用方括号:[]   -- 数组数据类型array(T) 数组是强数据类型e1,e2,d3...   toTypeName() -- 查看变量的数据类型

CREATE TABLE test_array
(
    name String, 
    hobby Array(String)
) ENGINE = Log

insert into test_array values
('张三',['读书','爬山','散步']),
('李四',['read','hiking','dance']),
('王五',array('吃','睡','喝','玩'));

select * from test_array;

insert into test_array values ('张三2',['读书','爬山','散步']);
insert into test_array values ('李四2',['read','hiking','dance']);
insert into test_array values ('王五2',array('吃','睡','喝','玩'));

-- clickhouse 会利用多核处理器将数据分块存储、计算
select * from test_array;

-- 查询数组中的数据
select *, hobby[1] from test_array;

-- 遍历数组中每个元素,给每个元素加上'abc'
select arrayMap(e -> concat(e, 'abc'), hobby) from test_array;

3.7 Tupe 元组

是一个特殊的数据类型,集合
可以存储任意的数据类型,在定义的时候声明数据类型和数据元素个数
元组类型由1~n 个元素组成,每个元素之间允许设置不同的数据类型,且彼此之间不要求兼容。无组同样支持类型推断,
其推断依据仍然以最小存储代码为原则。与数组类似,元组也可以使用两种方式定义

常规方式tuple(T):元组中可以存储多种数据类型,但是要注意数据类型的顺序
Tuple(String, UInt8, Date)

select tuple(1, 'abc', 12.33) as x, toTypeName(x);

┌─x───────────────┬─toTypeName(tuple(1, \'abc\', 12.33))─┐
│ (1,'abc',12.33) │ Tuple(UInt8, String, Float64)        │
└─────────────────┴──────────────────────────────────────┘

select (1, 2, 'hello') as x, toTypeName(x);
┌─x─────────────┬─toTypeName(tuple(1, 2, \'hello\'))─┐
│ (1,2,'hello') │ Tuple(UInt8, UInt8, String)        │
└───────────────┴────────────────────────────────────┘

创建tuple表及查询示例:

-- 注意:建表的时候使用元组的需要制定元组的数据类型
create table test_tuple(
    name String,
    info Tuple(String, String, UInt8)
) engine=Memory;

insert into test_tuple values
    ('zss', ('M', 'coder', 23)),
    ('lss', tuple('F', 'coder', 23));

select * from test_tuple;

┌─name─┬─info─────────────┐
│ zss  │ ('M','coder',23) │
│ lss  │ ('F','coder',23) │
└──────┴──────────────────┘

-- 通过下标查询tupe数据
select name, info.1, info.2, info.3 from test_tuple;

┌─name─┬─tupleElement(info, 1)─┬─tupleElement(info, 2)─┬─tupleElement(info, 3)─┐
│ zss  │ M                     │ coder                 │                    23 │
│ lss  │ F                     │ coder                 │                    23 │
└──────┴───────────────────────┴───────────────────────┴───────────────────────┘

3.8 Nested 嵌套表结构

Nested 是一种嵌套表结构。一张数据表,可以定义任意多个嵌套类型字段,但每个字段的嵌套层级只支持一级,
即嵌套表内不能继续使用嵌套类型。对于简单场景的层级关系或关联关系,使用嵌套类型也是一种不错的选择。

create table test_nested (
    id Int8,
    name String,
    hobby Nested(
        hid Int8,
        h1 String,
        h2 String
    )
)engine=Memory;

查看表结构:
┌─name──────┬─type──────────┬─default_type─┬─default_expression─┐
│ id        │ Int8          │              │                    │
│ name      │ String        │              │                    │
│ hobby.hid │ Array(Int8)   │              │                    │
│ hobby.h1  │ Array(String) │              │                    │
│ hobby.h2  │ Array(String) │              │                    │
└───────────┴───────────────┴──────────────┴────────────────────┘

嵌套类型本质是一种多维数组的结构。嵌套表中每个字段都是一个数组,并且行与行之间数组的长度无须对齐。
需要注意的是,在同一行数据内每个数组字段的长度必须相等。

-- 插入数据
insert into test_nested values (1, 'zss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);
insert into test_nested values (2, 'lss', [1,2,3],['吃','喝','睡'],['eat','drink','sleep']);

-- 查询数据    
select * from test_nested;

┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─hobby.h2────────────────┐
│  1 │ zss  │ [1,2,3]   │ ['吃','喝','睡'] │ ['eat','drink','sleep'] │
└────┴──────┴───────────┴───────────────┴─────────────────────────┘
┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─hobby.h2────────────────┐
│  2 │ lss  │ [1,2,3]   │ ['吃','喝','睡'] │ ['eat','drink','sleep'] │
└────┴──────┴───────────┴───────────────┴─────────────────────────┘

-- 复杂查询数据
select id, name, hobby.hid, hobby.h1, hobby.h1[1] from test_nested;

┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─arrayElement(hobby.h1, 1)─┐
│  1 │ zss  │ [1,2,3]   │ ['吃','喝','睡'] │ 吃                         │
└────┴──────┴───────────┴───────────────┴───────────────────────────┘
┌─id─┬─name─┬─hobby.hid─┬─hobby.h1──────┬─arrayElement(hobby.h1, 1)─┐
│  2 │ lss  │ [1,2,3]   │ ['吃','喝','睡'] │ 吃                         │
└────┴──────┴───────────┴───────────────┴───────────────────────────┘

3.9 复杂数据类型

3.9.1 domain

-- Domain pojo beans:https://clickhouse.tech/docs/zh/sql-reference/data-types/domains/ipv4/
域名类型分为IPv4和IPv6两类,本质上它们是对整型和字符串的进一步封装。IPv4类型是基于UInt32封装的

(1)出于便携性的考量,例如IPv4类型支持格式检查,格式错误的IP数据是无法被写入的,例如:INSERT INTO IPv4_test values('www.nauu.com', '192.0.0.1')

(2)出于性能的考量,同样以IPv4为例,IPv4使用UInt32存储,相比String 更加紧凑,占用的空间更小,查询性能更快。IPv6类型是基于FixedString(16) 封装的,它的使用方法与IPv4别无二致,在使用Domain类型的时候还有一点需要注意,虽然它从表象上看起来与String 一样,但Domain 类型并不是字符串,所以它不支持隐式的自动类型转换。如果需要返回IP的字符串形式,则需要显式调用IPv4NumToString 或 IPv6NumToString 函数进行转换。

create table test_domain1(
    id Int8,
    ip IPv4
)engine=Memory;

insert into test_domain1 values(1, '192.168.133.1');
insert into test_domain1 values(1, '192.168.133');

create table test_domain2(
    id Int8,
    ip String
)engine=Memory;

insert into test_domain2 values(1, '192.168.133.1');
insert into test_domain2 values(1, '192.168.133');

四、数据库

数据库起到了命名空间的作用,可以有效规避命名冲突的问题,也为后续的数据隔离提供了支撑。任何一张数据表,都必须归属在某个数据库之下。

在CK中数据库也有自己的引擎,数据库目前支持的数据库引擎有5种:

1)Ordinary:默认引擎,在绝大多数情况下我们都会使用默认引擎,使用时无须刻意声明。在此数据库下可以使用任意类型的表引擎

2) Dictionary:字典引擎,此类数据库会自动为所有数据字典创建它们的数据表

3) Memory:内存引擎,用于存放临时数据。此类数据库下的数据表只会停留在内存中,不会涉及任何磁盘操作,当服务重启后数据会被清除

4) Lazy:日志引擎,此类数据库下只能使用Log系列的表引擎

5) MySQL:MySQL引擎,此类数据库下会自动拉取远端MySQL中的数据,并为它们创建MySQL表引擎的数据表

6)  MaterializeMySQL:MySQL数据同步;将MySQL数据全量或增量方式同步到clickhouse中,解决mysql服务并发访问压力过大的问题

4.1 MySQL 数据库引擎

MySQL数据库引擎

先在mysql中先创建好数据库db_mysql_test

  • 确认远程访问权限
  • 确认域名是否配置
create database school_score engine=MySQL('node-01:3306','school_score','root','aa_bb_CC1234');

这样就可以在clickhouse下查询mysql中的数据了

use school_score;
show tables;

在clickhouse 不能创建mysql引擎表。但可以在clickhouse插入数据到mysql;因为 clickhouse不支持delete删除数据、update更新操作;原因是clickhouse定位于olap分析,不支持事务

4.2 Log 家族【Log系列引擎】

Log家族,比较简单,数据少,测试使用,本地表,本地存储表数据。默认数据存储在:/var/lib/clickhouse/data/...

Log家族具有最小功能的轻量级引擎。当您需要快速写入许多小表(最多约100万行)并在以后整体读取它们时,该类型的引擎是最有效的

4.2.1 TinyLog引擎(数据不分块)

TinyLog引擎数据不分块,而Log会进行分块。所以效率上来说:TinyLog不如Log快,因为它是单线程的。

最简单的表引擎,用于将数据存储在磁盘上。每列都存储在单独的压缩文件中,写入时,数据将附加到文件末尾。

该引擎没有并发控制。

  1. 只支持并发读
  2. 如果同时从表中读取和写入数据,则读取操作将抛出异常;
  3. 如果同时写入多个查询中的表,则数据将被破坏。
-- 建表
create table tb_tinylog(id Int8, name String, age Int8, birthDay Date) engine=TinyLog;

-- 插入数据
insert into tb_tinylog values(1,'马云',56, '1990-01-01'),(2,'马化腾',55, '1990-01-01'),(3,'马克思',123, '1990-01-01');

-- 查询数据
select * from tb_tinylog;

ll /var/lib/clickhouse/data/default/test_db

-rw-r--r-- 1 root root  29 Jan 10 15:17 age.bin
-rw-r--r-- 1 root root  32 Jan 10 15:17 birthDay.bin
-rw-r--r-- 1 root root  29 Jan 10 15:17 id.bin
-rw-r--r-- 1 root root  54 Jan 10 15:17 name.bin
-rw-r--r-- 1 root root 121 Jan 10 15:17 sizes.json

数据存储在机器的磁盘上,每列一个文件,插入数据向列文件的后面追加

再插入一条数据后,存储列数据的文件的大小增加了

age.bin 和 id.bin, name.bin 是压缩过的对应的列的数据,sizes.json 中记录了每个 *.bin 文件的大小:

cat sizes.json

[root@node-01 tb_tinylog]# cat sizes.json 
{"yandex":{"age%2Ebin":{"size":"29"},"birthDay%2Ebin":{"size":"32"},"id%2Ebin":{"size":"29"},"name%2Ebin":{"size":"54"}}}[root@node-01 tb_tinylog]#

补充说明,如果表损坏,需要将表删除、表对应的元数据删除,然后重启clickhouse-server服务

[root@node-01 test_db]# rm -rf /var/lib/clickhouse/data/test_db/tb_tinylog
[root@node-01 test_db]# rm -rf /var/lib/clickhouse/metadata/test_db/tb_tinylog.sql

这种表引擎的典型用法是 write-once:

  1. 首先只写入一次数据,然后根据需要多次读取。此引擎适用于相对较小的表(建议最多1,000,000行)。
  2. 如果有许多小表,则使用此表引擎是适合的,因为它比需要打开的文件更少。当拥有大量小表时,可能会导致性能低下。不支持索引。

4.2.2 StripLog (数据分块列在一起)

在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎。

-- 建表
create table stripe_log_table (
    timestamp DateTime,
    message_type String,
    message String
) engine=StripeLog;

5、数据表

ClickHouse 数据表的定义语法,是在标准SQL的基础上建立的,所以熟悉数据库的读者们在看到接下来的语法时,应该会感到熟悉。ClickHouse 目前提供了三种最基本的建表方法!但是注意的是在CK中建表一定要指定表的引擎,那么表的引擎的详细文档在后面。

5.1 创建表

create table [if not exists] [db_name.]table_name (
name1 [type][DEFAULT|MATERLIALIZED|ALIAS expr],
name2 [type][DEFAULT|MATERLIALIZED|ALIAS expr],
省略...
) ENGINE=engine

第一种建表方式:

create table test_db.test1(
    id Int16 DEFAULT 0 comment '用户的标识',
    name String comment '用户姓名',
    age UInt8 comment '用户年龄'
) ENGINE=Log;

上述语句将会在default 默认的数据库下创建一张内存表。注意末尾的ENGINE 参数,它被用于指定数据表的引擎。表引擎决定了数据表的特性,也决定了数据将会被如何存储及加载。例如示例中使用的Memory表引擎,是ClickHouse最简单的表引擎,数据只会被保存在内存中,在服务重启时数据会丢失。

第二种方式建表:

这种方式其实就是复制已经存在的一张的表结构,可用于数据的备份,可用于多个数据库之间复制表结构

CREATE TABLE [IF NOT EXISTS] [db_name.]table_name AS [db_name2.]table_name2[ENGINE=engine];

示例:

create database newdb;
use newdb;

-- 将复制test_db 数据库中的test1 表的表结构
create table tb_test1 as test_db.test1;
desc tb_test1;

第三种方式建表:

通过SELECT 查询的方式创建表,同时也会导入查询的结果数据

-- 语法
CREATE TABLE [IF NOT EXISTS] [db_name.]table_name ENGINE=engine AS SELECT ...

示例

create table tb_log engine=Memory as select * from test_db.tb_tinylog;

5.2 删除表

DROP TABLE [IF EXISTS] [db_name.]table_name;

5.3 临时表

ClickHouse 也有临时表的概念,创建临时表的方法是在普通表的基础之上添加TEMPORARY 关键字,相比普通表而言,临时表也如下两点特殊之处:

  • 它的生命周期是会话绑定的,所以它只支持Memeory 表引擎,如果会话结束,数据表就会被销毁;
  • 临时表不属于任何数据库所以在它的建表语句中,既没有数据库参数也没有表引擎参数

临时表的有优先级大于系统中的表,一般用于集群之间的数据传播的载体

临时表的创建语法如下:

CREATE TEMPORARY TABLE [IF NOT EXISTS] table_name (
  name1 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
  name2 [type] [DEFAULT|MATERIALIZED|ALIAS expr],
  ...
)

-- 直接创建临时表,临时表不属于任何一个数据库,也不会持久保存,不用指定引擎
create temporary table tb_tmp(id Int8, name String); -- 临时表不需要指定表的引擎

-- 创建临时表并加载数据
create temporary table log as select * from test_log;

-- 将临时表的数据导入到当前数据库表中,实现不同数据库的数据迁移
create table tb_log engine=Log as select * from log;

我们可以理解成临时表会将当前数据库中已经存在的同名表覆盖隐藏,当出现操作的时候,如果有临时表,那么会操作临时表!

临时表:

  1. 不属于任何数据库
  2. 会话断开以后表删除,不会持久化
  3. 如果本地表和临时表冲突,临时表优先
  4. 数据库之间的数据迁移
create table tb_name engine=Log as select * from db.tb;

create temporary table log as select * from test_db.test_log;
create table tb_log engine=Log as select * from log;

5.4 视图

5.4.1 普通视图

ClickHouse拥有普通和物化两种视图,其中物化视图拥有独立的存储,而普通视图只是一层简单的查询代理

CREATE VIEW [IF NOT EXISTS] [db_name.]view_name AS SELECT ...

普通视图不会存储任何数据,它只是一层单酏的SELECT 查询映射,起着简化查询、明晰语义的作用,对查询性能不会有任何增强。假设有一张普通视图 view_tb_v1,它是基于数据表 tb_v1创建的,那么下面的两格SELECT 查询是完全等价的。

SELECT * FROM tb_v1
-- tb_v1 的视图
SELECT * FROM view_tb_v1;

示例:

create table tb_teacher (
    tid Int8,
    name String,
    age UInt8,
    gender String,
    sal Float64
)engine=Log;

insert into tb_teacher values
    (1, 'wbb', 27, 'm', 20000),
    (2, 'lbb', 25, 'f', 30000),
    (3, 'mbb', 26, 'm', 40000),
    (4, 'sbb', 37, 'f', 50000),
    (5, 'lbb', 17, 'm', 60000);


create view teacher_view as select name, sal from tb_teacher;
-- 普通视图不存储数据,只是一个指向
select * from teacher_view;

5.4.2 物化视图

物化视图支持表引擎,相当于特殊的表,数据保存形式由它的表引擎决定,创建物化视图的完整语法如下所示:

create materialized view mv_log engine=Log populate as select * from log;
在磁盘上有表目录,目录中的文件和映射表的结构一样

-- 物化视图 特殊的表 结构 引擎 持久化
create materialized view m_teacher_view as engine=Log populate as select * from tb_teacher;

select * from m_teacher_view;

-- 向普通表tb_teacher插入数据
insert into tb_teacher values(6, 'xingge', 48, 'm', 1500);

-- 查询物化视图中的数据,同步数据
select * from m_teacher_view;

5.5 分区表

数据分区(partition)和数据分片(shard)是完全不同的两个概念。数据分区是针对本地数据而言的,是数据的一种纵向切分。而数据分片是数据的一种横向切分。数据分区对于一款OLAP数据库而言意义非凡:借助数据分共,在后续的查询过程中能够跳过不必要的数据目录,从而提升查询的性能。合理地利用分区特性,还可以变相实现数据的更新操作,因为数据分区支持删除、替换和重置操作。假设数据表按照月份分区,那么数据就可以按月份的粒度被替换更新。分区虽好,但不是所有的表引擎都可以使用这项特性,目前只有合并树(MergeTree)家族系列的表引擎才支持数据分区。接下来通过一个简单的例子演示分区表的使用方法。首先由PARTITION BY 指定分区键,并将其格式化为年月的形式:

create table tb_partition(
    cid String,
    ctime DateTime,
    money Float64
)engine=MergeTree() -- MergeTree家族最简单的引擎
partition by toYYYYMM(ctime) -- 按照年月来分区
order by cid -- 指定排序字段; 当排序字段与主键字段是同一个字段时,就会将主键字段不指定
primary key cid;

-- 插入数据
insert into tb_partition values
(1, '2020-12-01 11:00:21', 100),
(2, '2020-12-02 11:12:21', 300),
(3, '2020-11-01 11:00:21', 200);

-- 查询tb_partition表的分区信息
select table, partition, engine, path from system .parts where table='tb_partition';

-- 再次插入数据,进入到/var/lib/clickhouse/data/test_db/tb_partition/ 会发现11、12月份的数据都各有2个块
insert into tb_partition values
(4, '2020-12-01 11:00:21', 100),
(5, '2020-12-02 11:12:21', 300),
(6, '2020-11-01 11:00:21', 200);

-- 合并数据
optimize table tb_partition; -- 一次合并两个分区

-- 进入到/var/lib/clickhouse/data/test_db/tb_partition/ 会发现11、12月份的数据都各有1个块
-- 之前老的分区,默认8分钟会被删除

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/890340.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全之XXE攻击

0x01 什么是 XXE 个人认为&#xff0c;XXE 可以归结为一句话&#xff1a;构造恶意 DTD 介绍 XXE 之前&#xff0c;我先来说一下普通的 XML 注入&#xff0c;这个的利用面比较狭窄&#xff0c;如果有的话应该也是逻辑漏洞。 既然能插入 XML 代码&#xff0c;那我们肯定不能善罢…

图像分类-demo(Lenet),tensorflow和Alexnet

目录 demo(Lenet) 代码实现基本步骤&#xff1a; TensorFlow 一、核心概念 二、主要特点 三、简单实现 参数: 模型编译 模型训练 模型评估 Alexnet model.py train.py predict.py demo(Lenet) PyTorch提供了一个名为“torchvision”的附加库&#xff0c;其中包含…

【在Linux世界中追寻伟大的One Piece】信号捕捉|阻塞信号

目录 1 -> 信号捕捉初识 2 -> 阻塞信号 2.1 -> 信号其他相关常见概念 2.2 -> 在内核中的表示 2.3 -> sigset_t 2.4 -> 信号集操作函数 2.5 -> sigprocmask 2.6 -> sigpending 3 -> 捕捉信号 3.1 -> 内核如何实现信号的捕捉 3.2 ->…

VBA高级应用30例应用3Excel中的ListObject对象:选择表的一部分

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

【Spring】获取 Cookie和Session

回顾 Cookie HTTP 协议自身是属于“无状态”协议 无状态&#xff1a;默认情况下&#xff0c;HTTP 协议的客户端和服务器之间的这次通信和下次通信之间没有直接的联系 但是在实际开发中&#xff0c;我们很多时候是需要知道请求之间的关联关系的 例如登录网站成功后&#xff…

Linux高效查日志命令介绍

说明&#xff1a;之前介绍Linux补充命令时&#xff0c;有介绍使用tail、grep命令查日志&#xff1b; Linux命令补充 今天发现仅凭这两条命令不够&#xff0c;本文扩展介绍一下。 命令一&#xff1a;查看日志开头 head -n 行数 日志路径如下&#xff0c;可以查看程序启动是否…

安装和配置k8s可视化UI界面dashboard-1.20.6

安装和配置k8s可视化UI界面dashboard-1.20.6 1.环境规划2.初始化服务器1&#xff09;配置主机名2&#xff09;设置IP为静态IP3&#xff09;关闭selinux4&#xff09;配置主机hosts文件5&#xff09;配置服务器之间免密登录6&#xff09;关闭交换分区swap&#xff0c;提升性能7&…

系统架构设计师考试背记精要

1、架构的本质&#xff1a; &#xff08;1&#xff09;软件架构为软件系统提供了一个结构、行为和属性的高级抽象。&#xff08;2&#xff09;软件架构风格是特定应用领域的惯用模式&#xff0c;架构定义一个词汇表和一组约束。 2、数据流风格&#xff1a;适合于分阶段做数据处…

Springboot从入门到起飞-【day01】

个人主页→VON 收录专栏→Springboot从入门到起飞 一、前言 经过了近两个月的沉淀开始了新专栏的学习&#xff0c;经过深思熟虑还是决定重新学习java&#xff0c;因为基础部分东西太多太乱就不进行逐一的更新了&#xff0c;等到学完了一同进行更新。 二、Springboot简要概述 …

汽车免拆诊断案例 | 2013款宝马116i车偶尔加速不良

故障现象  一辆2013款宝马116i车&#xff0c;搭载N13B16A 发动机&#xff0c;累计行驶里程约为12.1万km。车主反映&#xff0c;该车行驶中偶尔加速无反应&#xff0c;且发动机故障灯异常点亮。 故障诊断 接车后试车&#xff0c;故障现象无法再现。用故障检测仪检测&#xff…

ChatGPT国内中文版镜像网站整理合集(2024/10/06)

一、GPT中文镜像站 ① yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画 ② chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③ AI Chat 支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;Mirror Site&#xff…

A股知识答题pk小程序怎么做?

A股知识答题pk小程序怎么做&#xff1f;以下是制作A股知识答题PK小程序的一般步骤&#xff1a; 一、 需求分析与规划&#xff1a; 明确目标&#xff1a;确定小程序的主要目标&#xff0c;比如是为了帮助用户学习A股知识、进行趣味竞赛&#xff0c;还是作为金融教育工具等。 …

2024年【金属非金属矿山(露天矿山)安全管理人员】考试题库及金属非金属矿山(露天矿山)安全管理人员实操考试视频

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年金属非金属矿山&#xff08;露天矿山&#xff09;安全管理人员考试题库为正在备考金属非金属矿山&#xff08;露天矿山&#xff09;安全管理人员操作证的学员准备的理论考试专题&#xff0c;每个月更新的金属非…

基于IDEA+SpringBoot+Vue+Uniapp的投票评选小程序系统的详细设计和实现

2. 详细视频演示 文章底部名片&#xff0c;联系我获取更详细的演示视频 3. 论文参考 4. 项目运行截图 代码运行效果图 代码运行效果图 代码运行效果图 代码运行效果图 代码运行效果图 5. 技术框架 5.1 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框…

Spring Cloud Stream 3.x+kafka 3.8整合

Spring Cloud Stream 3.xkafka 3.8整合&#xff0c;文末有完整项目链接 前言一、如何看官方文档(有深入了解需求的人)二、kafka的安装tar包安装docker安装 三、代码中集成创建一个测试topic&#xff1a;testproducer代码producer配置&#xff08;配置的格式&#xff0c;上篇文章…

【机器学习】逻辑回归|分类问题评估|混淆矩阵|ROC曲线|AUC指标 介绍及案例代码实现

文章目录 逻辑回归逻辑回归简介逻辑回归的数学基础逻辑回归原理概念损失函数 逻辑回归API函数和案例案例癌症分类预测 分类问题评估混淆矩阵分类评估方法 - 精确率 召回率 F1ROC曲线 AUC指标案例AUC 计算的API分类评估报告api 电信客户流失预测案例 逻辑回归 逻辑回归简介 ​…

matlab不小心删除怎么撤回

预设项——>删除文件——>移动至临时文件夹 tem临时文件夹下

SwiftUI 6.0(iOS 18)新增的网格渐变色 MeshGradient 解惑

概述 在 SwiftUI 中&#xff0c;我们可以借助渐变色&#xff08;Gradient&#xff09;来实现更加灵动多彩的着色效果。从 SwiftUI 6.0 开始&#xff0c;苹果增加了全新的网格渐变色让我们对其有了更自由的定制度。 因为 gif 格式图片自身的显示能力有限&#xff0c;所以上面的…

【自动驾驶汽车通讯协议】GMSL通信技术以及加串器(Serializer)解串器(Deserializer)介绍

文章目录 0. 前言1. GMSL技术概述2. 为什么需要SerDes&#xff1f;3. GMSL技术特点4.自动驾驶汽车中的应用5. 结论 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0c;虽然参考了他人的宝贵见解及成果&#xff0c;但是内容可能存在不准…

六西格玛黑带项目:TBX-02无人机飞行稳定性提升——张驰咨询

一、项目背景与问题定义 TBX-02是该公司最新发布的消费级无人机&#xff0c;面向摄影爱好者和户外探险者。产品上市后&#xff0c;通过客户反馈和实际测试数据发现&#xff0c;该无人机在复杂飞行环境中&#xff0c;如强风或快速移动时&#xff0c;存在明显的飞行抖动和稳定性…