整形
无符号整型
相比于上面,就是把负数部分挪到正数部分
浮点型
布尔型
Decimal
精确存储小数,超过最低有效数字会被丢弃(不是四舍五入)
decimal(10,2)中的“2”表示小数部分的位数,如果插入的值未指定小数部分或者小数部分不足两位则会自动补到2位小数,若插入的值小数部分超过了2为则会发生截断,截取前2位小数。
“10”指的是整数部分加小数部分的总长度,也即插入的数字整数部分不能超过“10-2”位,否则不能成功插入,会报超出范围的错误。
例如Decimal32(5),就是整数加小数一共9位,小数部分为5位
字符串
枚举类型
时间类型
数组
空
一般不要使用空,可以给一些默认值,空值会影响性能
--Nullable 表示可以为null
CREATE TABLE
t_null(
x Int8,
y Nullable(Int8)
) ENGINE TinyLog
INSERT INTO t_null VALUES (1, NULL), (2, 3)
还有很多数据类型,详情见官网
https://clickhouse.com/docs/zh/sql-reference/data-types/int-uint
引擎大小写敏感
需要写入许多小数据量(少于一百万行)的表的场景而开发的:
以列文件的形式保存在磁盘上,不支持索引,没有并发控制,一般保存少量数据,生产基本不会用
有很多种集成,并不真正拥有数据
cd /var/lib/clickhouse/
该目录下,有以下子目录:data是数据,metadata是表信息
CREATE TABLE `system`.users (
name String,
id UUID,
storage String,
auth_type Enum8('no_password' = 0, 'plaintext_password' = 1, 'sha256_password' = 2, 'double_sha1_password' = 3, 'ldap' = 4, 'kerberos' = 5),
auth_params String,
host_ip Array(String),
host_names Array(String),
host_names_regexp Array(String),
host_names_like Array(String),
default_roles_all UInt8,
default_roles_list Array(String),
default_roles_except Array(String),
grantees_any UInt8,
grantees_list Array(String),
grantees_except Array(String)
) ENGINE = MergeTree()
ORDER BY name;
clickhouse默认记录了数据的条数
分区
分区的目的就是降低扫描的范围,优化了查询速度,例如按照日志分区,就可以快速按照日期去查询,一个分区一个目录,
如果不分区,就会默认一个all分区,也就是把所有的数据放在一个分区
而且分区可以提供并行访问,一个分区一个线程,面对跨分区的查询,clickhouse会以分区为单位并行处理
分区文件命名格式如上图,含义是:
数据的写入于分区合并
-- 合并操作:
optimize table 表名 final;
-- 只针对某个分区进行合并
optimize table 表名 partition '分区名' final;
主键
clickhouse主键提供了一级索引,但并不唯一,而且并不是必须的
主键提供的索引为稀疏索引,默认间隔为8192,除非有大量的重复值,一般不需要改这个值,可以减少索引文件的大小,以及快速定位,但是没办法避免在一个区间内的扫描
排序
主键必须是order by的前缀字段,也就是 order by (id,name) ,那么主键就必须是id或者id,name
二级索引
在20.1.2.4之前,二级索引是实验阶段,需要手动开启,后续版本该设置已被删除,默认开启
建表语句如下:
CREATE TABLE test (
name String,
id UUID,
ctime Datetime,
INDEX a id TYPE minmax GRANULARITY 5
) ENGINE = MergeTree()
ORDER BY (name,id);
INDEX 索引名 字段名 TYPE minmax(索引的一种类型,这里是记录最小和最大值) GRANULARITY(粒度) 5
粒度,指的是在一级索引的前提下,在记录数据的粒度,比如说,有很多重复的数据,一级索引记录的区间为1-10,10-20,20-50等,想要判断35数据在哪一个区间,就需要判断3次,这里的粒度是5,也就是把五个区间合并为一个二级索引,使得区间的范围更大,查找更高效,也就是对于一级索引粒度的粒度
数据TTL
也就是数据存活时间,MergeTree可以单独对表或者列设置过期时间,过期了数据合并后就会变成默认值
CREATE TABLE test (
name String,
age UInt8 TTL ctime+interval 10 SECOND,
ctime Date
) ENGINE = MergeTree()
ORDER BY (name,ctime);
TTL 表中现有的时间列+(加或减固定时间值)interval 10 SECOND(时间单位:秒分时天月等), 这里表中现有的时间列 不能是主键
对于已经建好的表,可以修改列的定义加上ttl
ALTER TABLE 表名 MODIFY COLUMN 列名 列的数据类型 TTL 表中现有的时间列+interval 10 SECOND
表及别的TTL,相等于给所有的列加上过期时间,也可以在建表的时候,在order by 后加上TTL
ALTER TABLE 表名 MODIFY TTL 表中现有的时间列+interval 10 SECOND
CREATE TABLE test (
name String,
age UInt8 TTL ctime+interval 10 SECOND,
ctime Date
) ENGINE = ReplacingMergeTree(ctime)
ORDER BY (name,ctime);
是MergeTree的一个变种,因为临时查询时聚合的开销很大,增加了求和功能
提供一种分区内的预聚合,不能跨分区,也不是实时聚合,在同一批次插入(新版本)或者合并的时候会聚合,所以有可能出现没有聚合的情况
SummingMergeTree()里填写的是想要聚合的列,可以填多个,但必须是数值,如果不填就会以所有非维度列的字段来汇总(也就是除了order by 的字段),按插入顺序保留第一行
根据order by 的维度(类似于 group by )来聚合
CREATE TABLE test1 (
name String,
age UInt8 TTL ctime+interval 10 SECOND,
ctime Date
) ENGINE = SummingMergeTree(age)
ORDER BY (name,ctime);
insert
和标准sql基本一样
update 和 delete
语法例如:
alter table 表名 delete where 过滤条件
alter table 表名 update 字段名 = “” where 过滤条件
具体操作是先新增分区,并把旧的分区变为逻辑失效,直到触发分区合并,才会删除旧的分区
如果真的想要删除更新数据,也可以增加一个版本号,每次取数据的时候,只取版本号最大的数据,这样可以避免删除和更新操作,然后定期清理过期数据。也是一种思路
查询
基本和标准sql也差别不大
alter
基本和mysql一致
-- 新增字段
alter table 表名 add column 字段名 字段类型 after column1 ; (这里是指在那一列之后)
-- 修改字段类型
alter table 表名 modify column 列名 字段类型 ;
-- 删除字段
alter table 表名 drop column 列名;
导出
clickhouse-client --password xxxx --query '查询语句' --format CSVWithNames> 导出路径
clickhouse-client --password 123456 --query 'SELECT * from `system`.aggregate_function_combinators afc' --format CSVWithNames> /usr/data.csv
其他格式参考官网:
https://clickhouse.com/docs/zh/interfaces/formats