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 131072vi /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 = Loginsert 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分钟会被删除

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【排序】——1.冒泡排序法(含优化)

冒泡排序 1.原理 左边大于右边交换一趟排下来最大的交换到右边来(接下来所以文章用升序举例) 从左到右&#xff0c;相邻元素进行比较。 每次比较一轮&#xff0c;就会找到序列中最大的一个&#xff08;最小的一个——降序&#xff09;。这个数就会从序列的最右边冒出来。 以…

算法时间、空间复杂度(二)

目录 大O渐进表示法 一、时间复杂度量级的判断 定义&#xff1a; 例一&#xff1a;执行2*N&#xff0b;1次 例二&#xff1a;执行MN次 例三&#xff1a;执行已知次数 例四:存在最好情况和最坏情况 顺序查找 冒泡排序 二分查找 例五&#xff1a;阶乘递归 ​编辑 例…

JIT详解

文章目录 JIT为什么说 Java 语言“编译与解释并存”&#xff1f; JIT原理JVM 架构简览JIT 编译流程JIT 编译器的实现优化策略方法内联逃逸分析 JIT 在Java中&#xff0c;JIT&#xff08;Just-In-Time&#xff09;编译器是Java虚拟机&#xff08;JVM&#xff09;的一个重要组成…

韩国 NEL动物医疗中心:犬二尖瓣修复术连获成功

“守护心脏的神之手” 在小型犬心脏疾病根本治疗&#xff08;犬心脏修复手术&#xff09;方面取得重大突破&#xff0c;已成功完成 16 例手术。 韩国 NEL动物医疗中心&#xff08;NEL ANIMAL MEDICAL CENTER&#xff09;严泰欽院长带领的心脏手术团队&#xff0c;为 16 只宠物…

Lumerical学习——分析工具(Analysis tools)

一、分析工具和模拟环境&#xff08;Analysis tools and the simulation environment&#xff09; 模拟计算完成后&#xff0c;模拟计算数据紧接着写到模拟工程文件中&#xff1b;甚至当模拟计算提前结束时计算得到的部分数据集也会写到文件中。当模拟完成后单击退出按钮、或者…

【行业观察】三折机不够看?苹果研发四折叠屏iPhone

随着智能手机市场的日益成熟&#xff0c;消费者对手机形态和功能的需求也在不断升级。近年来&#xff0c;折叠屏手机凭借其独特的形态和更大的显示面积&#xff0c;成为了市场的新宠。而在这场折叠屏手机的竞争中&#xff0c;苹果作为智能手机行业的领头羊&#xff0c;自然也不…

Jmeter脚本录制、Badboy脚本录制

目录 Jmeter脚本录制 Badboy脚本录制 Jmeter脚本录制 1、首先添加一个http测试脚本记录器 2、选择目标控制器&#xff0c;把录制的内容放到的地方 3、分组&#xff0c;就是在录制的时候&#xff0c;每一步操作之间间隔方式&#xff0c;根据自己需要进行选择 4、开启浏览…

AI开发-三方库-Hugging Face-Pipelines

1 需求 需求1&#xff1a;pipeline支持的任务类型 需求2&#xff1a;推理加速使用CPU还是GPU 需求3&#xff1a;基于pipeline的文本分类示例 需求4&#xff1a;pipeline实现原理 模型使用步骤&#xff08;Raw text -》Input IDs -》Logits -》Predictions&#xff09;&…

跨域问题及常用的5种解决方案

1.什么是跨域问题&#xff1f; 跨域问题通常指的是在浏览器中由于同源策略的限制而产生的问题。同源策略&#xff08;Same-origin policy&#xff09;是浏览器的一种安全措施&#xff0c;它要求请求的域名、协议和端口必须与提供资源的网站相同。当一个网页尝试访问另一个来源…

基于SpringBoot+Vue+uniapp的在线招聘平台的详细设计和实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

图论day62|拓扑排序理论基础、117.软件构建(卡码网)、最短路径之dijkstra理论基、47.参加科学大会(卡码网 第六期模拟笔试)

图论day62|拓扑排序理论基础、117.软件构建&#xff08;卡码网&#xff09;、最短路径之dijkstra理论基、47.参加科学大会&#xff08;卡码网 第六期模拟笔试&#xff09; 拓扑排序理论基础117.软件构建&#xff08;卡码网&#xff09;最短路径之dijkstra理论基础47.参加科学大…

IT招聘乱象的全面分析

近年来&#xff0c;IT行业的招聘要求似乎越来越苛刻&#xff0c;甚至有些不切实际。许多企业在招聘时&#xff0c;不仅要求前端工程师具备UI设计能力&#xff0c;还希望后端工程师精通K8S服务器运维&#xff0c;更有甚至希望研发经理掌握所有前后端框架和最新开发技术。这种招聘…

day-67 二叉树展开为链表

思路 深度优先遍历&#xff1a;首先将二叉树进行前序遍历&#xff0c;将每个遍历的节点存入一个链表当中 解题过程 将链表还原为只有右子树的二叉树即可 Code /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* Tr…

Hi3061M开发板——系统时钟频率

这里写目录标题 前言MCU时钟介绍PLLCRG_ConfigPLL时钟配置另附完整系统时钟结构图 前言 Hi3061M使用过程中&#xff0c;AD和APT输出&#xff0c;都需要考虑到时钟频率&#xff0c;特别是APT&#xff0c;关系到PWM的输出频率。于是就研究了下相关的时钟。 MCU时钟介绍 MCU共有…

认识Java的异常

异常机制 异常机制指的是程序出现错误时&#xff0c;程序的处理方式。 程序的错误分为三种&#xff1a; 编译错误&#xff1a;由于没有遵循对于语言的语法规则&#xff0c;编辑器可以自动发现并提示的错误位置和原因。逻辑错误&#xff1a;程序没有按照预期的顺序执行。运行…

FreeRTOS应用开发学习

了解FreeRTOS 任务相关API FreeRTOS任务创建API FreeRTOS 中&#xff0c;任务的创建有两种方法&#xff0c;一种是使用动态创建&#xff0c;一种是使用静态创建。动态创建时&#xff0c;任务控制块和栈的内存是创建任务时动态分配的&#xff0c;任务删除时&#xff0c;内存可…

申请商家转账到零钱功能所需材料及必过攻略

商家转账到零钱功能的快速开通方法&#xff0c;可以归纳为以下几个步骤&#xff1a; 一、确认商户资格与账号状态 1. 商户类型&#xff1a;该功能通常只对公司性质的商户开放&#xff0c;个体工商户及小微商户暂时无法申请。商家需为微信支付认证用户。 2. 账号状态&#xff…

网络层及ip报头

★★★★★默写&#xff1a; A类&#xff1a;0~127 B类&#xff1a;128~191 C类&#xff1a;192~223 A类私网&#xff1a;10.0.0 - 10.255.255.255 B类私网&#xff1a;172.16.0.0 - 172.31.255.255 C类私网&#xff1a;19.168.0.0 - 192.168.255.255 特殊&#xff1a; 0.0.0…

新手爬虫DAY1

这个错误信息表明在你的Python程序中&#xff0c;re.search() 函数没有找到预期的匹配项&#xff0c;因此返回了 None。当你尝试在 None 对象上调用 group(1) 方法时&#xff0c;Python 抛出了一个 AttributeError。 具体来说&#xff0c;错误发生在 pc.py 文件的第6行&#x…

AI大模型与相对论的结合点的思考、应用及相对论原理与公式表达

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI大模型与相对论的结合点的思考、应用及相对论原理与公式表达。在阐述相对论原理的基础上&#xff0c;通过数学复杂公式&#xff0c;分析了人工智能大模型在相对论领域的应用前景。文章深入挖掘了两大领域之间的联…