mysql ,clickhouse 语法对比
选择查询
[WITH expr_list|(subquery)]
SELECT [DISTINCT] expr_list
[FROM [db.]table | (subquery) | table_function] [FINAL]
[SAMPLE sample_coeff]
[ARRAY JOIN ...]
[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN (subquery)|table (ON )|(USING )
[PREWHERE expr]
[WHERE expr]
[GROUP BY expr_list] [WITH TOTALS]
[HAVING expr]
[ORDER BY expr_list] [WITH FILL] [FROM expr] [TO expr] [STEP expr]
[LIMIT [offset_value, ]n BY columns]
[LIMIT [n, ]m] [WITH TIES]
[UNION ALL ...]
[INTO OUTFILE filename]
[FORMAT format]
with (CTE 公用表表达式)
限制:
1.不支持递归查询。
2.当在section中使用子查询时,它的结果应该是只有一行的标量。
3.Expression的结果在子查询中不可用。
使用范例:https://clickhouse.tech/docs/zh/sql-reference/statements/select/with/
sample 采样子句
该 SAMPLE 子句允许`近似于` SELECT 查询处理:启用数据采样时,不会对所有数据执行查询,而只对特定部分数据(样本)执行查询
适用于以下情况:
1.当你`有严格的时间需求`(如\<100ms),但你不能通过额外的硬件资源来满足他们的成本。
2.当您的`原始数据不准确`时,所以近似不会明显降低质量。
3.业务需求的`目标是近似结果`(为了成本效益,或者向高级用户推销确切结果)。
注:您只能使用采样中的表 MergeTree 族,并且只有在表创建过程中指定了采样表达式
SAMPLE Clause Syntax | 产品描述 |
---|---|
SAMPLE k |
这里 k 是从0到1的数字。 |
SAMPLE n |
这里 n 是足够大的整数。 例如, SAMPLE 10000000 |
使用时 SAMPLE n 子句,你不知道处理了哪些数据的相对百分比。 所以你不知道聚合函数应该乘以的系数。 使用 _sample_factor 虚拟列得到近似结果,该 _sample_factor 列包含动态计算的相对系数:
eg:
SELECT sum(PageViews * _sample_factor)
FROM visits
SAMPLE 10000000
ARRAY JOIN
该表具有包含该初始列中的每个单独数组元素的列,而其他列的值将被重复显示.
arrays_test:
┌─s───────────┬─arr─────┐
│ Hello │ [1,2] │
│ World │ [3,4,5] │
│ Goodbye │ [] │
└─────────────┴─────────┘
ARRAY JOIN 子句:(过滤两边都有的记录)
eg:
SELECT s, arr FROM arrays_test ARRAY JOIN arr;
┌─s─────┬─arr─┐
│ Hello │ 1 │
│ Hello │ 2 │
│ World │ 3 │
│ World │ 4 │
│ World │ 5 │
└───────┴─────┘
LEFT ARRAY JOIN 子句:(以LEFT ARRAY JOIN 左边表arrays_test记录为基准)
SELECT s, arr FROM arrays_test LEFT ARRAY JOIN arr;
┌─s───────────┬─arr─┐
│ Hello │ 1 │
│ Hello │ 2 │
│ World │ 3 │
│ World │ 4 │
│ World │ 5 │
│ Goodbye │ 0 │
└─────────────┴─────┘
建表语法
PARTITION BY (自定义分区键)
MergeTree 系列的表(包括 可复制表 )可以`使用分区`,
基于 MergeTree 表的 物化视图 也`支持分区`.
新数据插入到表中时,这些数据会存储为按主键排序的新片段(块)。插入后 10-15 分钟,`同一分区`的各个片段会`合并为一整个片段`。
可以通过 system.parts 表查看`表片段和分区信息`:
SELECT partition,name,active FROM system.parts WHERE table = 'visits';
┌─partition─┬─name───────────┬─active─┐
│ 201901 │ 201901_1_3_1 │ 0 │
│ 201901 │ 201901_1_9_2 │ 1 │
│ 201901 │ 201901_8_8_0 │ 0 │
│ 201901 │ 201901_9_9_0 │ 0 │
│ 201902 │ 201902_4_6_1 │ 1 │
│ 201902 │ 201902_10_10_0 │ 1 │
│ 201902 │ 201902_11_11_0 │ 1 │
└───────────┴────────────────┴────────┘
name含义(以201901_1_3_1为例):
201901 是分区名称。
1 是数据块的最小编号。
3 是数据块的最大编号。
1 是块级别(即在由块组成的合并树中,该块在树中的深度)。
对于分区的操作
分区剥离: ALTER TABLE table_name DETACH PARTITION partition_expr; eg:ALTER TABLE visits DETACH PARTITION 201901; `detached` 目录存放着使用 DETACH 语句从表中卸载的片段。损坏的片段不会被删除而是也会移到该目录下。服务器不会去使用detached目录中的数据片段。因此你可以随时添加,删除或修改此目录中的数据 – 在运行 ATTACH 语句前,服务器不会感知到。 注:如果存在分片副本: 注意仅能在副本的leader节点上执行该操作。想了解副本是否是leader节点,需要在 system.replicas 表执行 SELECT 操作。或者,可以很方便的在所有副本节点上执行 DETACH操作,但除leader外其它的副本节点会抛出异常。
删除分区: ALTER TABLE table_name DROP PARTITION partition_expr; eg: 从表中删除指定分区。该操作会将分区标记为不活跃的,然后在大约10分钟内删除全部数据。
删除已剥离的分区|数据块: ALTER TABLE table_name DROP DETACHED PARTITION|PART partition_expr eg: 从detached目录中删除指定分区的特定部分或所有数据。
关联分区|数据块(把剥离的分区|数据块 加载回去) ALTER TABLE table_name ATTACH PARTITION|PART partition_expr eg: ALTER TABLE visits ATTACH PARTITION 201901; ALTER TABLE visits ATTACH PART 201901_2_2_0; 从detached目录中添加数据到数据表。可以添加整个分区的数据,或者单独的数据块。
复制分区: ALTER TABLE table2 ATTACH PARTITION partition_expr FROM table1 该操作将 table1 表的数据分区复制到 table2 表的已有分区。注意table1表的数据不会被删除。 为保证该操作能成功运行,下列条件必须满足: 1. 2张表必须有相同的结构 2. 2张表必须有相同的分区键
替换分区: ALTER TABLE table2 REPLACE PARTITION partition_expr FROM table1 该操作将 table1 表的数据分区复制到 table2表,并替换 table2表的已有分区。注意table1表的数据不会被删除. 为保证该操作能成功运行,下列条件必须满足: 1. 2张表必须有相同的结构 2. 2张表必须有相同的分区键
将分区移动到表: ALTER TABLE table_source MOVE PARTITION partition_expr TO TABLE table_dest 该操作将 table_source表的数据分区移动到 table_dest表,并删除table_source表的数据。 为保证该操作能成功运行,下列条件必须满足: 1. 2张表必须有相同的结构 2. 2张表必须有相同的分区键 3. 2张表必须属于相同的引擎系列(可复制表或不可复制表) 4. 2张表必须有相同的存储方式
更有具体细节请看更改分区及文件快操作
注:访问 如何设置分区表达式可获取设置分区表达式的详细信息。
ORDER BY (排序键)
可以是一组列的元组或任意的表达式。
ORDER BY (CounterID, EventDate) 。
如果没有使用 PRIMARY KEY 显式的指定主键,ClickHouse 会使用排序键作为主键。
如果不需要排序,可以使用 ORDER BY tuple().
主键
排序键
SETTINGS index_granularity = 8192
SETTINGS — 控制 MergeTree 行为的额外参数
index_granularity — 索引粒度。索引中相邻的『标记』间的数据行数。默认值,8192 。参考数据存储。
数据存储
`表` 由按 `主键排序` 的 `数据片段`(DATA PART)组成。当数据被插入到表中时,会创建多个数据片段并按主键的字典序排序。
(分区包含片段)不同分区的数据会被分成不同的片段,ClickHouse 在后台合并数据片段以便更高效存储。
不同分区的数据片段不会进行合并。合并机制并不保证具有相同主键的行全都合并到同一个数据片段中。
数据片段(DATA PART)的格式:数据片段可以以 Wide 或 Compact 格式存储:
Wide 格式:每一列都会在文件系统中存储为单独的文件:
min_bytes_for_wide_part,min_rows_for_wide_part 在数据片段中可以使用Wide格式进行存储的最小字节数/行数.如果数据片段中的字节数或行数少于相应的设置值,数据片段会以 Compact 格式存储,否则会以 Wide 格式存储
Compact 格式:所有列都存储在一个文件中。Compact 格式可以提`高插入量少` `插入频率频繁`时的性能。
(片段中包含颗粒)每个数据片段被逻辑的分割成颗粒(granules),颗粒是 ClickHouse 中进行数据查询时的最小不可分割数据集,每个颗粒总是包含`整数个行`。每个颗粒的第一行通过该行的`主键值进行标记`,
颗粒相关参数:颗粒的大小通过表引擎参数 index_granularity 和 index_granularity_bytes 控制,
index_granularity:颗粒行数的在 [1, index_granularity] 范围中
index_granularity_bytes: 规定颗粒的大小,如果单行的大小大于了index_granularity_bytes,这种情况下,颗粒的大小等于该行的大小。
(索引文件存储的是标记)ClickHouse 会为每个数据片段创建一个`索引文件来存储这些标记`,对于每列,无论它是否包含在主键当中,都会存储类似标记。这些标记让你可以在列文件中直接找到数据。
)
数据模型(建表规则)
星型模型
是一种多维的数据关系,它由一个事实表(Fact Table)和一组维表(Dimension Table)组成。每个维表都有一个维作为主键,所有这些维的主键组合成事实表的主键。事实表的非主键属性称为事实(Fact),它们一般都是数值或其他可以进行计算的数据.
星型架构是一种`非正规化的结构`,多维数据集的每一个维度都直接与事实表相连接,所以数据`有一定的冗余`.
(每个维表都与事实表直接关联)
雪花模型
当有一个或多个维表`没有直接连接到事实表上`,而是通过其他维表连接到事实表上时,其图解就像多个雪花连接在一起。
雪花模型是对星型模型的扩展。
它对星型模型的维表进一步层次化,原有的各维表可能被扩展为小的事实表,形成一些局部的 "层次 " 区域,这些被分解的表都连接到主维度表而不是事实表。
通过最大限度地减少数据存储量以及联合较小的维表来改善查询性能。雪花型结构`去除了数据冗余`。
(有的维表不与事实表直接相连)
数据类型对比
ClickHouse | MySQL | Comment |
---|---|---|
UInt8, UInt16, UInt32, UInt64 | TINYINT UNSIGNED, SMALLINT UNSIGNED, INT UNSIGNED, BIGINT UNSIGNED | |
Int8, Int16, Int32, Int64 | TINYINT SIGNED, SMALLINT SIGNED, INT SIGNED, BIGINT SIGNED | |
Float32, Float64 | FLOAT, DOUBLE | Supports inf, -inf, nan, recommended NOT to use by ClickHouse! |
String | BLOB, TEXT, VARCHAR, VARBINARY | No encoding. Recommended to use UTF-8. In fact behaves like a BLOB. |
FixedString(n) | CHAR, BINARY | \0 padded. Less functions available than String, in fact it behaves like BINARY. |
Date | DATE | UNIX epoch date up to 2038. |
DateTime | DATETIME, TIMESTAMP | UNIX epoch timestamp up to 2038. |
Enum | ENUM | Similar to MySQL ENUM. Behaves like Int8/16. |
Array(type) | n.a. | Array of type. Closest equivalent in MySQL is JSON? Not well supported. |
Tuple() | n.a. | |
Nested() | n.a. | Closest equivalent in MySQL is JSON? |
AggregateFunction() | n.a. | |
Set | n.a. |
关于 MaterializeMySQL引擎 所创建的 ReplacingMergeTree 表的 查询问题
ReplacingMergeTree 自动增加了 _sign 和 _version 字段:
_version 用作 ReplacingMergeTree 的 ver 版本参数,每当监听到 insert、update 和 delete 事件时,在 databse 内全局自增。
_sign 则用于标记是否被删除,取值 1 或者 -1
改写mysql语句时要注意的问题
#mysql中 类似如下语句,直接在ReplacingMergeTree表中执行会报错(while processing query: '_sign = 1,。。。):
select assist from tb_account_amount_assist where trans_date = '2020-06-18' limit 10;
#必须加上_sign标志,以表明筛选未删除的行:
select assist from tb_account_amount_assist where trans_date = '2020-06-18' and _sign limit 10;
#问题:Not found column account_cd in block: while executing 'INPUT : 2 -> account_cd Nullable(String) : 2'
导致select 出的列必须包含account_cd,这样会对改写sql很不方便。
#原因
是因为上游mysql表有 索引 导致下游表排序有变化
ORDER BY (assumeNotNull(trans_date), assumeNotNull(contractno), assumeNotNull(account_cd), id)
删除上游除主键之外的索引,可以规避此问题。
# 令 (不完善的地方),如果上游mysql表已经创建了索引,那么就算之后再删除,下游的表结构ORDER BY也不会有任何变化
mysql 上游创建表 ,不支持 like语法,会报错:DB::Exception: Cannot convert create like statement to ClickHouse SQL: While executing MYSQL_QUERY_EVENT. The query: CREATE TABLE tb_contract_balance_new like tb_contract_balance.
#结论 创建表不能使用如下语句:
CREATE TABLE tb_contract_balance_new like tb_contract_balance;
insert into tb_contract_balance_new select * from tb_contract_balance;
TODO: (不完善的地方)上下游断连之后如何解决?
上下游断连之后如何解决
目前没有类似于mysql的容错机制,根据2020.7的issue判断(https://github.com/ClickHouse/ClickHouse/issues/14573),
暂时不支持mysql式的主从同步功能,因为库级别的同步很难保证其他数据库中的表结构是正确的。从issue中看,至少到今年一月,这个问题依然没有解决
临时解决方法,监控下游位置点变化(/var/lib/clickhouse/store/b0d/b0d83a5f-9ef7-47df-a451-a3548a2a98e3/.metadata),一旦出现一段时间内停滞情况,报警,拉全量上游数据
性能调优
基础参数
max_threads: 查询使⽤的线程数量,默认为核数⼀半
max_memory_usage: 单次查询允许使⽤的内存量
max_memory_usage_for_all_users:clickhouse进程允许使⽤的内存量,
通常需要考虑为OS预留内存
max_bytes_before_external_group_by: GROUP BY 操作使⽤内存超过该阈值后, 数据会写⼊磁盘,建议设置为max_memory_usage/2
max_concurrent_queries: 最⼤并发数限制
max_bytes_before_external_sort: order by 排序溢写磁盘阈值
background_pool_size: 后台线程组
简单说说ClickHouse的概述以及优势
ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。由号称“俄罗斯 Google”的 Yandex 开发而来,在 2016 年开源,在计算引擎里算是一个后起之秀,在内存数据库领域号称是最快的。由于它有几倍于 GreenPlum 等引擎的性能优势,所以不少人都选择将其安装云服务器中使用。
ClickHouse 是一个列导向数据库,是原生的向量化执行引擎。它在大数据领域没有走 Hadoop 生态,而是采用 Local attached storage 作为存储,这样整个 IO 可能就没有 Hadoop 那一套的局限。它的系统在生产环境中可以应用到比较大的规模,因为它的线性扩展能力和可靠性保障能够原生支持 shard + replication 这种解决方案。它还提供了一些 SQL 直接接口,有比较丰富的原生 client。另外就是它比较快。
以下是ClickHouse作为分析型数据库的特点:
1. 速度快
ClickHouse性能超过了市面上大部分的列式存储数据库,相比传统的数据ClickHouse要快100-1000倍,ClickHouse还是有非常大的优势:
100Million 数据集:
ClickHouse比Vertica约快5倍,比Hive快279倍,比MySQL快801倍
1Billion 数据集:
ClickHouse比Vertica约快5倍,MySQL和Hive已经无法完成任务了
2. 功能多
ClickHouse支持数据统计分析各种场景
支持类SQL查询
支持繁多库函数(例如IP转化,URL分析等,预估计算/HyperLoglog等)
支持数组(Array)和嵌套数据结构(Nested Data Structure)
支持数据库异地复制部署
3. 文艺范
不理睬Hadoop生态,走自己的路
目前任何具有x86_64,AArch64或PowerPC64LE CPU架构的Linux,FreeBSD或Mac OS X上运行。
而ClickHouse的缺点:
不支持Transaction:想快就别想Transaction
聚合结果必须小于一台机器的内存大小:不是大问题
缺少完整的Update/Delete操作
支持有限操作系统
clickhouse 备份
冻结 表
1.确认您的影子目录为空:ls /var/lib/clickhouse/shadow/
2.echo -n 'alter table [库名].[表名] freeze' | clickhouse-client
3.如果发生灾难,请保存备份
mkdir /var/lib/clickhouse/backup && cp -r /var/lib/clickhouse/shadow/ backup/[my-backup-name]
4.最后,为下次清理备份源
rm -rf /var/lib/clickhouse/shadow/*
clickhouse-backup
https://www.modb.pro/db/41261