clickhouse学习笔记
概念
clickhouse是一个用于联机的(OLAP)的列式数据库管理系统(DBMS)。
ALAP(联机分析)的关键特征。
- 绝大多数都是读请求。
- 数据以相当大的批次(>1000)行更新,而不是单行更新,或者根本没有更新。
- 已添加到数据库中的数据不能修改。
- 对于读取,从数据库中提取相当多的行,但只提取列的一小部分。
- 宽表,即每个表含有大量的列。
- 查询相对较少(通常每台服务器每秒查询数百次或者更少。
- 对于普通查询允许延迟大于50毫秒。
- 列中的数据相对较少:数字和段字符串(例如,每个URL60个字符)。
- 处理单个查询时需要高吞吐量(每台服务器每秒可达数十亿行)
- 事务不是必须的。
- 对数据一致性要求低。
- 每个查询有一个大表,除了它以外,其他都很小。
- 查询结果明显小于元数据。换句话说,数据经过过滤或聚合,因此结果适合于单个服务器的RAM中。
列式数据库更适合OLAP场景的原因
输入/输出
- 针对分析类查询,通常只需要读取表的一小部分。在列式数据库中你可以只读曲你需要的数据。例如:如果只需要读取100列种的5例,这将减少20倍的I/O消耗。
- 由于数据库总是打包成批量读取,所以压缩是非常容易的。同时数据按列分别存储这也更容易压缩。进一步降低了I/O体积。
- 由于I/O的降低,这将帮助更多的数据被策、系统缓存。
CPU
由于执行一个查询需要处理大量的行,因此在整个向量上执行所有的操作将比在每一行上执行所有的操作更加高效。同时这将有助于实现一个几乎没有调用成本的查询引擎。如果不这样做,使用任何一个机械硬盘,查询引擎都不可避免的停止CPU进行等待,所以,在数据按列存贮并且按列执行是很有意义的。
有两种方法可以做到这一点:
- 向量引擎:所有的操作都是为向量而不是为单个值编写的。这意味着多个操作之间的不再需要频繁的调用,并且调用的成本基本可以忽略不计。操作代码包含一个优化的内部循环。
- 代码生成:生成一段代码,包含查询中的所有操作。
ClickHouse的特性
- 真正的列式数据库管理系统
- 数据压缩
- 数据的磁盘存储
- 多核心,并行处理
- 多服务器分布式处理
- 支持sql
- 向量引擎
- 实时的数据更新
- 索引
- 适合在线查询
- 支持近似计算
- 自适应连接算法(Adaptive join Algorithm)
- 支持数据复制和数据完整性
- 角色的访问控制
限制
- 没有完整的事务支持
- 缺少高频率,低延迟的修改或删除已存在数据的能力。仅能用于批量删除或修改数据
- 稀疏索引使得clickhouse不适合通过其键检索单行的点查询
Clickhouse的性能
- 单个大查询的吞吐量大
- 处理短查询的延迟时间低
- 处理大量短查询的吞吐量大
- 数据的写入性能好
由于学习的时候并没有连接clickhouse,因此便在clickhouse的体验demo的平台做了一些练习
-- SELECT * from hits_v1
-- SELECT count(*) from hits_v1
-- SELECT * from hits_v1 WHERE WatchID >=7194583557826607391
-- WITH '2014-03-22 12:34:00' as ts_upper_bound,1 as aa
-- SELECT WatchID,EventTime
-- FROM hits_v1
-- SELECT
-- MobilePhoneModel AS Phone,
-- count() * 10 AS PageViews
-- FROM datasets.visits_v1
-- SAMPLE 0.1
-- WHERE NOT empty(Phone)
-- AND StartDate BETWEEN '2014-03-23' AND '2014-03-30'
-- GROUP BY Phone
-- ORDER BY PageViews DESC;
-- WHERE
-- EventTime >= ts_upper_bound AND
-- JavaEnable = aa
-- SELECT
-- protocol(Referer) AS Protocol,
-- path(Referer) AS Path,
-- domain(Referer) AS Domain,
-- topLevelDomain(Referer) AS TopLevelDomainDomain,
-- queryString(Referer) AS Query,
-- arrayMap(x -> arrayMap(y -> decodeURLComponent(y), splitByChar('=', x)) , Params) as Decoded
-- FROM `visits_v1`
-- WHERE NOT empty(Referer)
-- AND StartDate BETWEEN '2014-03-23' AND '2014-03-30'
-- AND Params != emptyArrayString()
-- LIMIT 10;
-- WITH sum(JavaEnable) as s
-- SELECT
-- count(*) as num,
-- formatReadableSize(s),
-- EventTime
-- FROM hits_v1
-- GROUP BY EventTime
-- ORDER BY num
-- LIMIT 100
-- SELECT
-- timezone() AS srv_tz,
-- toDateTime('2020-03-25 12:00:00') AS time_srv,
-- toDateTime('2020-03-25 12:00:00', 'Europe/Moscow') AS time_msk,
-- toDateTime('2020-03-25 12:00:00', 'UTC') AS time_utc,
-- toTypeName(time_srv) as tn_time_srv,
-- toTypeName(time_msk) as tn_time_msk,
-- toTypeName(time_utc) as tn_time_utc,
-- dateDiff('hour', time_msk, time_utc, 'UTC') AS diff_hours,
-- formatDateTime(time_utc, '%F %T', timezone()) AS utc_t_format,
-- toTimeZone(time_utc, timezone()) AS utc_to_tz
-- SELECT sum(ALL number) FROM numbers(1000000001);
-- SELECT DISTINCT RegionID FROM hits_v1 ORDER BY RegionID LIMIT 100
-- show tables
-- show DATABASES
-- SELECT * from hits_100m_obfuscated
-- SELECT * from visits_v1 LIMIT 10
-- select count(*) from visits_v1
-- select CounterID,RefererRegions,num,now() from visits_v1 array Join RefererRegions as num LIMIT 100
-- select Referer from visits_v1 LIMIT 10
-- select * from visits_v1 LIMIT 1;
-- SELECT 'some/long/path/to/file' AS a, basename(a)
-- SELECT number / 3 AS x, round(x) FROM system.numbers LIMIT 100
-- SELECT toValidUTF8('\x61\xF0\x80\x80\x80b')
-- SELECT length('hahahh') as len
-- SELECT format('{1} {2} {2}', 'World', 'Hello','!')
-- SELECT alphaTokens('abca1abc454cdqafcs')
-- SELECT splitByChar('f','sfdsguifgiu')