1. 何为ClickHouse?
ClickHouse为一款用于在线分析处理查询(OLAP)的列式数据库管理系统(DBMS)。
2. 何为OLAP?
OLAP场景中对大数据集进行实时查询时,具备如下特征的复杂分析查询:
1)数据集可能包含数十亿或数万亿行的数据;
2) 数据在包含多个列的表中;
3)某些特定查询可能需选择少数列;
4)结果必须以毫秒级或秒级返回;
3. 列式及行式数据库
行式DBMS,数据按行存储,一行数据中所有数值物理上相邻存储。
列式DBMS,数据按列存储,同一列的数值存储到一起。
4.为何OLAP场景列式数据库工作较好
列式数据库比较适合OLAP场景:它们在处理大部分查询时至少要快100倍。因为,行式数据库中,数据是按行读取的,哪怕查询只需数据行中一个列,也要读取整个数据行才行;相反,列式数据库中,数据可以按列读取,查询需要哪个列,就只读取那个列就行,从而避免了无效读取行中其他列的成本。
5. ClickHouse为何如此之快?
ClickHouse利用所有可用的系统资源尽可能快的全力处理每个分析查询。其独一无二的实现最快OLAP数据库所需的分析能力和底层细节关注的组合,使得这成为可能。
6. 实时处理分析查询
行式数据库中,一个数据行相关数值物理相邻存储。行式数据库(DBMS)的例子包括Oracle,MySQL,Postgres,DB2和MS SQL Server等传统关系库。
列式数据库中,不同列的数值分别存储,相同列的数据存储在一起。列式数据库(DBMS)的例子包括Vertica,Paraccel (Actian Matrix和Amazon Redshift), Sybase IQ,Exasol,Infobright, InfiniDB, MonetDB (VectorWise和Actian Vector),LucidDB, SAP HANA,Google Dremel,Google PowerDrill,Druid, kdb+。
数据存储的不同顺序适合不同场景。数据访问场景取决于具体查询,查询频率,以及比例;每类查询读多少数据——行,列和字节;数据读和改的关系;工作数据的规模和本地使用的多少;是否使用事务,其如何隔离;数据复制和逻辑完整的需求;每个查询对延迟和吞吐的需求,等等。
系统负载越高,合理系统设计以匹配使用场景就越重要,并且,该设计也变得更精确。没有哪个系统会适合所有截然不同的场景。如果一个系统能适合各种场景,高负载下,该系统在不同场景下将会同样性能低下,或仅仅在某个或某些少数场景下有较好表现。
7. OLAP场景关键属性
1)表是“宽表”,这意味着它们包含大量的列;
2)数据量很大,且处理单个查询时要求高吞吐量(高达每个服务器每秒数十亿行数据);
3)列值相当小:数字和短串(例如:每个URL60字节);
4)查询抽取大量数据行,但仅涉及一小部分列;
5)简单查询,需要50ms的延迟;
6)每个查询中有一个大表,其余都是小表;
7)查询结果比源数据要小得多。换句话多,数据被过滤和汇聚,结果能存储于单服务器内存(RAM)中。
8)查询相对较少(通常每秒每服务器数百查询);
9)插入操作(Insert)会大批量进行,而不是单行;
10)无需事务。
很容易看到OLAP场景与其他大部分场景(像OLTP或键值访问)的不同。因此,试着用OLTP或键值数据库处理分析查询而想获得好性能是没意义的。例如:如果你将MongoDB 或Redis用于分析目的,你将得到与OLAP数据库相比的非常差的性能。
8. Input/output
1)对于分析查询,仅需读取表中一小部分列。在列式数据库中,可以只读需要的数据。例如:如果需要100列中的5列,那么,就可以降低20倍的IO。
2)由于按包读取数据,因此,压缩数据比较容易。列中的数据压缩也比较容易。这进一步降低了所需的IO。
3)由于减少了IO,会有更多的数据存储于系统缓存中。
比如,“对每个广告平台的记录进行计数”的查询,需要读取一个“广告平台ID”列,这样,不压缩要耗费1字节。如果大部分瓶颈并非来自广告平台,预期该列可达10倍的压缩率。用一种快速压缩算法时,数据解压速度可能达到每秒至少数GB的速度。换句话说,该查询在一台服务器上处理数据的速度可达几乎每秒数十亿行。现实中确实可以达到这个速度。
9. CPU
因为执行一个查询需要处理大量数据行,为整个向量而非单个数据行调度所有操作,或者,实施查询引擎而几乎没有调度成本,都有助于节省CPU成本。否则,任何像样的磁盘子系统,查询解释器不可避免的会导致CPU停滞。因此,数据尽可能按列存储和处理意义重大。
要想如此,目前有两种方式:
1)向量引擎。所有操作为向量而非单独的数值编写。这意味着不必经常调用操作,且调度成本也可以忽略不计。操作代码包含优化过的内部循环。
2)代码产生。为查询产生的代码自包含所有的间接调用。
行式数据库不会这么处理,因为运行简单查询时这么做没有意义。但是,也有例外。例如:MemSQL处理查询时用“代码产生”来降低延迟。(相比较,分析型DBMS要求优化吞吐而非延迟。)
注意为了CPU效率,查询语言必须是声明式的(SQL or MDX),或者,至少是向量(J, K)。查询仅应包含允许优化的隐式循环。