详情访问主页:
https://clickhouse.tech/docs/v20.3/en/
- 启动服务端
service clickhouse-server start
- 启动交互式客户端
clickhouse-client
支持多行输出:
clickhouse-client -m
create database db_name;
use db_name;
select currentDatabase();
drop database db_doit19;
日志与 TinyLog 的不同之处在于,«标记» 的小文件与列文件存在一起。这些标记写在每个数据块上,并且包含偏移量,这些偏移量指示从哪里开始读取文件以便跳过指定的行数。这使得可以在多个线程中读取表数据。对于并发数据访问,可以同时执行读取操作,而写入操作则阻塞读取和其它写入。Log 引擎不支持索引。同样,如果写入表失败,则该表将被破坏,并且从该表读取将返回错误。Log 引擎适用于临时数据,write-once 表以及测试或演示目的。
建表
create table testolog (
id Int16,
name String,
age UInt8,
gender Enum('男'=1,'女'=2))
engine=Log;
导入数据
insert into testolog values(1,'guodegang',50,'男');
insert into testolog values(2,'yuqian',51,'男');
insert into testolog values(3,'高峰',55,'男');
多次插入的数据会分开显示
最简单的表引擎,用于将数据存储在磁盘上。每列都存储在单独的压缩文件中,写入时,数据将附加到文件末尾。
该引擎没有并发控制
**- 只支持并发读**
- 如果同时从表中读取和写入数据,则读取操作将抛出异常;
- 如果同时写入多个查询中的表,则数据将被破坏。
service clickhouse-server start
clickhouse-client -m
create database db_user;
create table tb_TinyLog(
id UInt8,
name String,
score Float64
)
engine = TinyLog;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y8461F1L-1607486606040)(https://gitee.com/abin571/abinde-ty/raw/master/img/20201204195631716.png)]
insert into tb_TinyLog values(1,'zss','98.3'),(1,'lss','80.5');
insert into tb_TinyLog values(3,'ww',70.6);
data.bin — 数据文件。
index.mrk — 带标记的文件。标记包含了已插入的每个数据块中每列的偏移量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jejdlvjg-1607486606046)(https://gitee.com/abin571/abinde-ty/raw/master/img/20201204195631716.png)]
在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎。
StripeLog 引擎将所有列存储在一个文件中。*对每一次 Insert 请求,**ClickHouse* 将数据块追加在表文件的末尾,逐列写入。
StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。
create table tb_StripeLog(
id UInt8,
name String,
score Float64
)
engine = StripeLog;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vNouKnFP-1607486606048)(https://gitee.com/abin571/abinde-ty/raw/master/img/20201204195631716.png)]
insert into tb_StripeLog values(1,'zss','98.3'),(1,'lss','80.5');
insert into tb_StripeLog values(3,'ww','50.6');
共同属性
数据存储在磁盘上。
写入时将数据追加在文件末尾。
不支持突变操作。
不支持索引。
这意味着
SELECT
在范围查询时效率不高。非原子地写入数据。
如果某些事情破坏了写操作,例如服务器的异常关闭,你将会得到一张包含了损坏数据的表。
差异
Log 和 StripeLog 引擎支持:
并发访问数据的锁。
INSERT
请求执行过程中表会被锁定,并且其他的读写数据的请求都会等待直到锁定被解除。如果没有写数据的请求,任意数量的读请求都可以并发执行。并行读取数据。
在读取数据时,ClickHouse 使用多线程。 每个线程处理不同的数据块。
Log 引擎为表中的每一列使用不同的文件。StripeLog 将所有的数据存储在一个文件中。因此 StripeLog 引擎在操作系统中使用更少的描述符,但是 Log 引擎提供更高的读性能。
TinyLog 引擎是该系列中最简单的引擎并且提供了最少的功能和最低的性能。TingLog 引擎不支持并行读取和并发数据访问,并将每一列存储在不同的文件中。它比其余两种支持并行读取的引擎的读取速度更慢,并且使用了和 Log 引擎同样多的描述符。你可以在简单的低负载的情景下使用它。
MergeTree系列的表引擎是ClickHouse数据存储功能的核心。它们提供了用于弹性和高性能数据检索的大多数功能:列存储,自定义分区,稀疏的主索引,辅助数据跳过索引等。
基本MergeTree表引擎可以被认为是单节点ClickHouse实例的默认表引擎,因为它在各种用例中通用且实用。
对于生产用途,ReplicatedMergeTree是必经之路,因为它为常规MergeTree引擎的所有功能增加了高可用性。一个额外的好处是在数据提取时自动进行重复数据删除,因此如果插入过程中出现网络问题,该软件可以安全地重试。
MergeTree引擎的主要缺点是它们很重。因此,典型的模式是没有太多。如果您需要许多小表(例如用于临时数据),请考虑使用Log engine family。
该MergeTree系列中的引擎旨在将大量数据插入表中。数据快速地逐个部分地写入表中,然后应用规则在后台合并这些部分。这种方法比插入期间连续重写存储中的数据效率更高。
这使您可以创建一个小的稀疏索引,以帮助更快地查找数据。
ClickHouse支持的某些分区操作比对相同数据,相同结果的常规操作更有效。ClickHouse还会自动切断在查询中指定了分区键的分区数据。这也提高了查询性能。
ReplicatedMergeTree表族提供数据复制。有关更多信息.
如有必要,可以在表中设置数据采样方法。
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster](
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
...
INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2 )
ENGINE = MergeTree()
ORDER BY expr
[PARTITION BY expr]
[PRIMARY KEY expr]
[SAMPLE BY expr]
[TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
[SETTINGS name=value, ...]
SAMPLE BY—用于采样的表达式。可选的。
- 如果使用采样表达式,则主键必须包含它。范例:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。
TTL—规则列表,用于指定行的存储持续时间并定义磁盘和卷之间零件自动移动的逻辑。可选的。
- 结果必须有一个Date或一DateTime列。例:
TTL date + INTERVAL 1 DAY- 规则的类型DELETE|TO DISK ‘xxx’|TO VOLUME 'xxx’指定了在满足表达式(达到当前时间)时要对零件执行的操作:删除过期的行,将零件(如果对零件中的所有行都满足表达式)移动到指定的磁盘(TO DISK ‘xxx’)或到音量(TO VOLUME ‘xxx’)。规则的默认类型为删除(DELETE)。可以指定多个规则的列表,但最多只能有一个DELETE规则。
SETTINGS—控制MergeTree(可选)行为的其他参数:
index_granularity—索引标记之间的最大数据行数。默认值:8192。请参见数据存储。
index_granularity_bytes—数据粒度的最大大小(以字节为单位)。默认值:10Mb。要仅按行数限制颗粒大小,请设置为0(不建议)。请参阅数据存储。
enable_mixed_granularity_parts—启用或禁用过渡以通过index_granularity_bytes设置控制颗粒尺寸。在版本19.11之前,只有index_granularity用于限制颗粒大小的设置。index_granularity_bytes从具有大行(数十和数百MB)的表中选择数据时,此设置可提高ClickHouse性能。如果您的表具有大行,则可以为表启用此设置以提高SELECT查询效率。
use_minimalistic_part_header_in_zookeeper— ZooKeeper中数据部件头的存储方法。如果为use_minimalistic_part_header_in_zookeeper=1,则ZooKeeper存储的数据较少。有关更多信息,请参阅“服务器配置参数”中的设置说明。
min_merge_bytes_to_use_direct_io—使用对存储磁盘的直接I / O访问所需的最小合并操作数据量。合并数据部分时,ClickHouse会计算要合并的所有数据的总存储量。如果卷超过min_merge_bytes_to_use_direct_io字节,ClickHouse将使用直接I / O接口(O_DIRECT选项)读取数据并将数据写入存储磁盘。如果为min_merge_bytes_to_use_direct_io = 0,则直接I / O被禁用。默认值:10 * 1024 * 1024 * 1024字节。
merge_with_ttl_timeout—重复与TTL合并之前的最小延迟(以秒为单位)。默认值:86400(1天)。
write_final_mark—启用或禁用在数据部分的末尾(最后一个字节之后)写入最终索引标记。默认值:1.不要关闭它。
merge_max_bloCK_size—合并操作的块中的最大行数。默认值:8192
storage_policy—存储策略。请参阅使用多个块设备进行数据存储。
min_bytes_for_wide_part,min_rows_for_wide_part—可以以Wide格式存储的数据部分中的最小字节/行数。您可以设置这些设置之一,全部或全部。请参阅数据存储。
建表
create table testoMTree(
id String ,
name String ,
city String
)
engine = MergeTree
order by id;
导入二次数据(数据是分开的)
insert into testoMTree values('id004','wb','HB'),('id005','DHT','HN'),('id006','ZXX','HLJ');
insert into testoMTree values('id011','wb2','HB'),('id007','DHT2','HN'),('id016','ZXX2','HLJ');
本地文件格式
drwxr-x---. 2 clickhouse clickhouse 177 Dec 5 06:35 all_1_1_0
drwxr-x---. 2 clickhouse clickhouse 177 Dec 5 06:35 all_2_2_0
drwxr-x---. 2 clickhouse clickhouse 6 Dec 5 06:31 detached
-rw-r-----. 1 clickhouse clickhouse 1 Dec 5 06:31 format_version.txt
[root@linux01 testoMTree]# pwd
/var/lib/clickhouse/data/default/testoMTree
[root@linux01 testoMTree]# cd all_1_1_0/
[root@linux01 all_1_1_0]# ll
total 40
-rw-r-----. 1 clickhouse clickhouse 320 Dec 5 06:35 checksums.txt
-rw-r-----. 1 clickhouse clickhouse 36 Dec 5 06:35 city.bin
-rw-r-----. 1 clickhouse clickhouse 48 Dec 5 06:35 city.mrk2
-rw-r-----. 1 clickhouse clickhouse 77 Dec 5 06:35 columns.txt
-rw-r-----. 1 clickhouse clickhouse 1 Dec 5 06:35 count.txt
-rw-r-----. 1 clickhouse clickhouse 42 Dec 5 06:35 id.bin
-rw-r-----. 1 clickhouse clickhouse 48 Dec 5 06:35 id.mrk2
-rw-r-----. 1 clickhouse clickhouse 37 Dec 5 06:35 name.bin
-rw-r-----. 1 clickhouse clickhouse 48 Dec 5 06:35 name.mrk2
-rw-r-----. 1 clickhouse clickhouse 12 Dec 5 06:35 primary.idx
- *.bin是按列保存数据的文件
- *.mrk保存块偏移量
- primary.idx保存主键索引
每次添加数据,都会在表目录下生成一个文件夹
合并数据
optimize table tb_tree1;
注意:MergeTree引擎数据可以重复
这个引擎是在 MergeTree 的基础上,添加了“处理重复数据”的功能,该引擎和MergeTree的不同之处在于它会删除具有相同主键 的重复项。
数据的去重只会在合并的过程中出现。
合并会在未知的时间在后台进行,所以你无法预先作出计划。有一些数据可能仍未被处理。因此,ReplacingMergeTree 适用于在后台清除重复的数据以节省空间,但是它不保证没有重复的数据出现。
(允许插入重复的数据,系统会在合并数据(optimize)时进行比较,保留最新的版本的数据。
使用演示:
建表/添加数据
create table testoRMTree(
id String ,
name String ,
v UInt8
)
engine = ReplacingMergeTree(v)
order by id;
--v是自定义的一个版本列,用来记录数据版本
insert into testoRMTree values ('a001','zss',10),('a002','lss',10) ;
insert into testoRMTree values ('a001','zss2',30),('a002','lss2',5) ;
┌─id───┬─name─┬──v─┐
│ a001 │ zss │ 10 │
│ a002 │ lss │ 10 │
└──────┴──────┴────┘
┌─id───┬─name─┬──v─┐
│ a001 │ zss2 │ 30 │
│ a002 │ lss2 │ 5 │
└──────┴──────┴────┘
合并数据
optimize table testoRMTree;
┌─id───┬─name─┬──v─┐
│ a001 │ zss2 │ 30 │
│ a002 │ lss │ 10 │
└──────┴──────┴────┘
--保留了版本号v,最大的数据
可以使用时间作为比较字符
create table tb_replacing_tree2(
id String ,
name String ,
accTime DateTime
)
engine = ReplacingMergeTree(accTime)
order by id ;
使用演示:
建表/插入数据
create table testoCMTree(
id String ,
name String ,
v UInt8,
s Int8
)
engine = CollapsingMergeTree(s)
order by id;
insert into testoCMTree values ('a001','lss',2,1) ;
insert into testoCMTree values ('a001','zss',1,1) ;
insert into testoCMTree values ('a001','zss2',3,-1);
合并数据
个人理解:-1会抵消最先输入的同主键的数据。
CollapsingMergeTree一般不使用
使用演示:
建表、添加数据
create table testoVCMTree(
id UInt8 ,
name String ,
sign Int8,
version UInt8
)
engine = VersionedCollapsingMergeTree(sign, version)
order by id ;
插入数据
insert into testoVCMTree values(1,'a',1,1),(1,'b',1,2) ;
insert into testoVCMTree values(1,'a2',1,3) ;
┌─id─┬─name─┬─sign─┬─version─┐
│ 1 │ a │ 1 │ 1 │
│ 1 │ b │ 1 │ 2 │
└────┴──────┴──────┴─────────┘
┌─id─┬─name─┬─sign─┬─version─┐
│ 1 │ a2 │ 1 │ 3 │
└────┴──────┴──────┴─────────┘
--相同主键的数据可以添加,但是在合并时会删除
insert into testoVCMTree values(1,'a',-1,2) ;
--对主键为1,版本号为2的数据进行折叠
┌─id─┬─name─┬─sign─┬─version─┐
│ 1 │ a │ 1 │ 1 │
│ 1 │ a2 │ 1 │ 3 │
└────┴──────┴──────┴─────────┘
使用演示:
建表/导入数据
create table testtosumtree(
id Int8 ,
name String ,
ctime Date ,
cost UInt8
)
engine=SummingMergeTree(cost)
order by id
partition by name ;
insert into testtosumtree values(1,'wangben','2020-12-06',1),(1,'shsh','2019-11-11',20) ;
insert into testtosumtree values(1,'wangben','2020-12-05',1),(1,'shsh','2019-11-11',20) ;
insert into testtosumtree values(1,'wangben','2020-12-03',1),(1,'shsh','2019-11-11',20) ;
insert into testtosumtree values(1,'wangben','2020-12-04',1),(1,'shsh','2019-11-11',20) ;
合并数据
合并数据时,一次合并(optimize)语句,只会合并一个分区,如果有多个分区,需要多次执行合并语句;
除了主键和引擎关键字段的其他关键字,在合并时,理论上保留最先输入的数值。
可以创建一个连接MySQL中某个数据库的数据库引擎,直接对MySQL进行映射,形成连接
使用演示:
create database db_ch_mysql engine=MySQL('linux01:3306','doit','root','root');
可以直接使用MySQL数据中的表.
注意:该数据库只读,不能添加或修改
使用演示:
create table tb_user(
id Int32 ,
name String
)
engine=MySQL('linux01:3306','doit','tb_user','root','root') ;
和MySQL类似,连接hdfs中的某个文件,映射为ClickHouse中的表
本地表、MySQL表和hdfs的表都可以互相关联操作
TSV和CSV
两种结构化数据文件格式(文本类型):
TSV是以tab键分隔数据
CSV是以逗号分隔数据
使用演示:
create table tb_ch_hdfs(
uid String ,
name String ,
city String ,
age UInt8
)
engine = HDFS("hdfs://linux01:8020/ch/data/user.tsv" , "TSV") ;
--关联hdfs可以使用*关联多个文件,但是不能指定目录(必须要指定到文件)
可以进行数据类型转换:
cast(val,'String')
cast(val as String)
File表引擎以特殊的文件格式(TabSeparated,Native等)将数据保存在文件中。
用法示例: File(Format)
支持的文件格式:
https://clickhouse.tech/docs/v20.3/en/interfaces/formats/#formats
create table tb_file_demo1(uid UInt16 , name String) engine=File(TabSeparated) ;
/var/lib/ClickHouse/data/default/tb_file_demo1
[root@linux01 tb_file_demo1]# vi data.TabSeparated 注意这个文件的名字不能变化
1001 TaoGe
1002 XingGe
1003 HANGGE
使用ClickHouse的方式读本地文件
echo -e "1,2\n3,4" | clickhouse-local -q "CREATE TABLE tb_local1 (a Int64, b Int64) ENGINE = File(CSV, stdin);select * from tb_local1;"
cat ./data.CSV | clickhouse-local -q "CREATE TABLE tb_local2 (id Int64, name String) ENGINE = File(CSV, stdin); select * from tb_local2 ;"
clickhouse-local -q
为固定写法将本地文件数据导入到ClickHouse表中
操作步骤:
在CH中建表
create table tb_client (id UInt16 , name String) engine=TinyLog ;
将数据导入
cat data.CSV | ClickHouse-client --query="INSERT INTO tb_client FORMAT CSV";
cat data.CSV | ClickHouse-client -q "INSERT INTO tb_client FORMAT CSV"; --一样的
cat data.CSV | ClickHouse-client -q "INSERT INTO tb_client FORMAT CSV"
–format_csv_delimiter="," ; --指定分隔符
cat shop.csv | clickhouse-client -q "create table test_shop(name String,ctime Date ,money Float64) engine = File(CSV , 0 );"---失败,不能创建表格
```
* 注意`FORMAT CSV` 大写
**数据导入注意事项 : **
全量数据导入:数据导入临时表 -> 导入完成后,将原表改名为tmp1 -> 将临时表改名为正式表 -> 删除原表
增量数据导入: 增量数据导入临时表 -> 将原数据除增量外的也导入临时表 -> 导入完成后,将原表改名为tmp1-> 将临时表改成正式表-> 删除原数据表
使用hive建表,指定文件格式
hive的文件保存在hdfs中
通过集成引擎hdfs,直接创建表格,参考第四章第2节,这里不再演示
在加载过程中,注意数据类型的匹配
在导入过程中,注意hive和CH对于不同文件格式的命名方式
在hive中的表数据存储格式:
ORCFILE
Parquet
TestFile
在CH中
ORC
Parquet
CSV、TSV
参考第四章3.3节
使用from直接查询本地文件
SELECT * FROM file('user.csv', CSV, 'id Int8 , name String , age Int8 , gender String')
第一个字段—文件名
第二个字段—文件格式
第三个字段—表构造
使用from查询hdfs中的文件
(文件可以是hive存储在hdfs中的,可以是本地的文件,或者其他hdfs中的符合CH格式的文件)
hdfs(URI, format, structure)
SELECT *
FROM hdfs(`hdfs://linux01:8020/user/hive/warehouse/db_doit19.db/tb_teacher2/000000_0`, ORC, 'name String , xz String ,xx String')
SELECT * FROM mysql('linux01:3306', 'db_doit19', 'tb_user', 'root', 'root') ;
使用方法与前两种大致相同
使用演示:
--建表
create table test_arrjoin(
id Int8 ,
arr Array(String)
)engine=Memory ;
--添加数据
insert into test_arrjoin values(1,['a1','a2']),(2,array('b1','b2','b3')),(3,[]) ;
┌─id─┬─arr──────────────┐
│ 1 │ ['a1','a2'] │
│ 2 │ ['b1','b2','b3'] │
│ 3 │ [] │
└────┴──────────────────┘
--使用array join进行分解
select id ,arr
from test_arrjoin
array join arr ;
┌─id─┬─arr─┐
│ 1 │ a1 │
│ 1 │ a2 │
│ 2 │ b1 │
│ 2 │ b2 │
│ 2 │ b3 │
└────┴─────┘
--left array join(按其他字段进行补全)
-- 如果对arr重新命名了,那么arr就可以代表原来的数组;如果没有as命名,arr就是被炸裂的字段名
select id ,arr ,x1
fromtest_arrjoin
left array join arr as x1 ;
┌─id─┬─arr─┐
│ 1 │ a1 │
│ 1 │ a2 │
│ 2 │ b1 │
│ 2 │ b2 │
│ 2 │ b3 │
│ 3 │ │
└────┴─────┘
--array join后面也可使用自定义的数组
select id , arr ,x
from test_arrjoin
array join[1,2,3] as x;
┌─id─┬─arr──────────────┬─x─┐
│ 1 │ ['a1','a2'] │ 1 │
│ 1 │ ['a1','a2'] │ 2 │
│ 1 │ ['a1','a2'] │ 3 │
│ 2 │ ['b1','b2','b3'] │ 1 │
│ 2 │ ['b1','b2','b3'] │ 2 │
│ 2 │ ['b1','b2','b3'] │ 3 │
│ 3 │ [] │ 1 │
│ 3 │ [] │ 2 │
│ 3 │ [] │ 3 │
└────┴──────────────────┴───┘
使用演示 :
-- 建表
create table test_grouparr(
id Int8 ,
name String
)engine = Log ;
-- 导入数据
insert into test_grouparr values(1,'a1'),(1,'a2'),(1,'a3'),(2,'b1'),(2,'b2'),(2,'b3') ;
┌─id─┬─name─┐
│ 1 │ a1 │
│ 1 │ a2 │
│ 1 │ a3 │
│ 2 │ b1 │
│ 2 │ b2 │
│ 2 │ b3 │
└────┴──────┘
-- 使用groupArray()聚合
select
id ,
groupArray(name) arr
from test_grouparr
group by id;
┌─id─┬─arr──────────────┐
│ 1 │ ['a1','a2','a3'] │
│ 2 │ ['b1','b2','b3'] │
└────┴──────────────────┘
-- arrayEnumerate(arr)函数:获取一个数组的全部索引,返回一个数组
select id , groupArray(name) arr , arrayEnumerate(arr) arr_index
from test_grouparr
group by id;
┌─id─┬─arr──────────────┬─arr_index─┐
│ 1 │ ['a1','a2','a3'] │ [1,2,3] │
│ 2 │ ['b1','b2','b3'] │ [1,2,3] │
└────┴──────────────────┴───────────┘
-- 可以通过array join 操作多个数组,前提是两个数组的长度要相同
select
id ,e ,i
from
(
select
id ,
groupArray(name) arr ,
arrayEnumerate(arr) arr2
--这里数组是怎么来的不影响,长度匹配就可以,
--[23,44,5555] arr2 结果相同
from
test_grouparr
group by id
)
array join
arr as e ,
arr2 as i ;
┌─id─┬─e──┬─i─┐
│ 1 │ a1 │ 1 │
│ 1 │ a2 │ 2 │
│ 1 │ a3 │ 3 │
│ 2 │ b1 │ 1 │
│ 2 │ b2 │ 2 │
│ 2 │ b3 │ 3 │
└────┴────┴───┘
ClickHouse中的SQL使用和hive/mysql大致相同,一些特殊语法使用方式不同,在此进行介绍:
-- 定义一个变量供select使用
with 'uid0001' as v
select * from tb_user where id = v ;
-- 查询一个结果供select使用(都是一个固定值)
with (select count(1) from tb_user) as cnt
select sum(age) / cnt from tb_user ;
-- 待验证
with tb_user as (select id , upper(name) from tb_user)
select * from tb_user ;
distinct 去重
FORMAT
-- 指定输出和输入的数据格式
clickhouse-client -q "select * from db_doit19.tb_user FORMAT XML"
输出的文件类型
file Creates a File-engine table.
merge Creates a Merge-engine table.
numbers Creates a table with a single column filled with integer numbers.
remote Allows you to access remote servers without creating a Distributed-engine table.
url Creates a Url-engine table.
mysql Creates a MySQL-engine table.
jdbc Creates a JDBC-engine table.
odbc Creates a ODBC-engine table.
hdfs Creates a HDFS-engine table.
limit by
-- 建表添加数据
create table tb_limit(
id Int8 ,
name String ,
score Float64
)engine=Log ;
insert into tb_limit values(1,'zss',77),(1,'zss',79),(1,'zss',99),(1,'zss',89) ;
insert into tb_limit values(2,'lss',66),(2,'lss',69),(2,'lss',61),(2,'lss',69) ;
┌─id─┬─name─┬─score─┐
│ 2 │ lss │ 66 │
│ 2 │ lss │ 69 │
│ 2 │ lss │ 61 │
│ 2 │ lss │ 69 │
└────┴──────┴───────┘
┌─id─┬─name─┬─score─┐
│ 1 │ zss │ 77 │
│ 1 │ zss │ 79 │
│ 1 │ zss │ 99 │
│ 1 │ zss │ 89 │
└────┴──────┴───────┘
-- 直接使用limit
select * from tb_limit order by score desc limit 2;
┌─id─┬─name─┬─score─┐
│ 1 │ zss │ 99 │
│ 1 │ zss │ 89 │
└────┴──────┴───────┘
-- 使用limit by 可以通过by实现分组,分组之后再取组内前limit个
select * from tb_limit order by score desc limit 2 by name;
┌─id─┬─name─┬─score─┐
│ 1 │ zss │ 99 │
│ 1 │ zss │ 89 │
└────┴──────┴───────┘
┌─id─┬─name─┬─score─┐
│ 2 │ lss │ 69 │
│ 2 │ lss │ 69 │
└────┴──────┴───────┘
empty()
--输入数组或字符串
--判断是否为空
--返回UInt8,是空返回1,不空返回0
notEmpty()
--与empty()相反
length()
--输入数组或字符串
--返回长度(UInt16)
emptyArrayString
--返回一个空数组,所有类型都可以
range(end), range(start, end [, step])
--直接返回一个UInt类型数组
--输入开始值,结束值,跳跃数量(默认1)
--使用演示:
linux01 :) select range(1,20,2);
SELECT range(1, 20, 2)
┌─range(1, 20, 2)────────────┐
│ [1,3,5,7,9,11,13,15,17,19] │
└────────────────────────────┘
array(x1, …), operator [x1, …]
--数组的构造函数
--使用此方法只能构造有参数的数组,想要空数组使用emptyArrayString
arrayConcat(arrays)
--合并数组(连接数组)
SELECT arrayConcat([1, 2], [3, 4], [5, 6]) AS res
┌─res───────────┐
│ [1,2,3,4,5,6] │
└───────────────┘
arrayElement(arr,n)
--取出arr数组中,索引为n的值
--n输入-1时取最后一个数值
has(arr, elem)
--判断数组中是否包含参数elem
hasAll(set, subset)
--检查一个数组是否是另一个数组的子集
hasAny(array1, array2)
--检查两个数组是否有某些元素相交。
hasSubstr(array1, array2)
--检查1数组是否包含2数组,且顺序完全相同
arrayCount([func,] arr1,…)
--高级函数:函数的参数,是其他函数或方法的函数
--输入:lambda表达式,数组
--返回数组中符合lambda表达式的元素的个数
SELECT arrayCount(x -> ((x + 10) > 100), [10, 20, 50, 90, 100, 110])
┌─arrayCount(lambda(tuple(x), greater(plus(x, 10), 100)), [10, 20, 50, 90, 100, 110])─┐
│ 2 │
└─────────────────────────────────────────────────────────────────────────────────────┘
visitParamHas(params, name)
--params:Json格式的行数据
--检查该行Json中是否存在内容为name的键
Geohash
与hive分区方法完全相同
create table tb_p2(
oid String ,
money Float64 ,
cDate Date
) engine = MergeTree
order by oid
partition by toMonth(cDate) ;
-- 月进行分区
insert into tb_p2 values ('002',99,'2020-12-01') ,('001',98,'2020-12-01') ,('003',199,'2020-12-02'),('004',299,'2020-11-02');
┌─oid─┬─money─┬──────cDate─┐
│ 001 │ 98 │ 2020-12-01 │
│ 002 │ 99 │ 2020-12-01 │
│ 003 │ 199 │ 2020-12-02 │
└─────┴───────┴────────────┘
┌─oid─┬─money─┬──────cDate─┐
│ 004 │ 299 │ 2020-11-02 │
└─────┴───────┴────────────┘
-- select数据与hive略有不同,不同分区会分开显示
windowFunnel(间隔时间)(toDateTime(时间字段),eventid = '事件1',eventid = '事件2',...) as funnel
使用说明 :
使用演示 :
建表/导入数据
CREATE TABLE test_funnel ( uid String, eventid String, eventTime UInt64) ENGINE = MergeTree PARTITION BY (uid, eventTime) ORDER BY (uid, eventTime);
cat funnel.csv | clickhouse-client -q "INSERT INTO test_funnel FORMAT CSV";
SELECT *
FROM test_funnel
ORDER BY (uid, eventTime) ASC
┌─uid──┬─eventid─┬──eventTime─┐
│ uid1 │ event1 │ 1551398100 │
│ uid1 │ event2 │ 1551398180 │
│ uid1 │ event3 │ 1551398260 │
│ uid1 │ event4 │ 1551398340 │
│ uid1 │ event1 │ 1551398500 │
│ uid1 │ event2 │ 1551398540 │
│ uid1 │ event3 │ 1551398580 │
│ uid1 │ event1 │ 1551398700 │
│ uid1 │ event2 │ 1551398705 │
│ uid2 │ event2 │ 1551398412 │
│ uid2 │ event3 │ 1551398415 │
│ uid3 │ event3 │ 1551398410 │
│ uid3 │ event4 │ 1551398413 │
└──────┴─────────┴────────────┘
使用漏斗函数查看事件
select
uid,
windowFunnel(100)
(toDateTime(eventTime),eventid = 'event1',eventid = 'event2',eventid = 'event3',eventid = 'event4') as funnel
from test_funnel
group by uid
order by uid;
┌─uid──┬─funnel─┐
│ uid1 │ 3 │
│ uid2 │ 0 │
│ uid3 │ 0 │
└──────┴────────┘
select uid,
windowFunnel(240)
(toDateTime(eventTime),eventid = 'event1',eventid = 'event2',eventid = 'event3',eventid = 'event4') as funnel
from test_funnel
group by uid
order by uid;
┌─uid──┬─funnel─┐
│ uid1 │ 4 │
│ uid2 │ 0 │
│ uid3 │ 0 │
└──────┴────────┘
select
uid,
windowFunnel(239)
(toDateTime(eventTime),eventid = 'event1',eventid = 'event2',eventid = 'event3',eventid = 'event4') as funnel
from test_funnel
group by uid
order by uid;
┌─uid──┬─funnel─┐
│ uid1 │ 3 │
│ uid2 │ 0 │
│ uid3 │ 0 │
└──────┴────────┘