什么是ClickHouse?

ClickHouse 是面向OLAP 的分布式列式DBMS.

在“正常”的面向行的DBMS中,数据按顺序进行存储:

5123456789123456789    1     Eurobasket - Greece - Bosnia and Herzegovina -
example.com     1      2011-09-01 01:03:02    6274717 1294101174      11409 
612345678912345678     0      33      6   
 http://www.example.com/basketball/team/123/match/456789.htmlhttp://www.example.com/basketball/team/123/match/987654.html 
   0      1366    768    32     10      3183      0     0      13      0\0   
1     1      0      0                     2011142 -1     0              0   
 01321    613    660    2011-09-01 08:01:17   0      0      0     0      utf-8 
1466    0     0      0      5678901234567890123             277789954      0 
   0      0      0      0

5234985259563631958    0     Consulting, Tax assessment, Accounting, Law     
1     2011-09-01 01:03:02    6320881  2111222333     213   
6458937489576391093    0     3      2      http://www.example.ru/       0     
800    600     16      10      2      153.1 0      0      10      63     1     
1      0     0                     2111678 000      0      588   368    240   
2011-09-01 01:03:17    4     0      60310  0     windows-1251    1466    0     
000             778899001      0     0      0      0     0

...

换句话说,与一行相关的所有值都被存储在一起。面向行的DBMS主要有MySQL,Postgres,MSSQL Server等等。

在面向列的DBMS中,数据存储如下:

WatchID:5385521489354350662   5385521490329509958    5385521489953706054 
 5385521490476781638    5385521490583269446   5385521490218868806   
5385521491437850694 5385521491090174022      5385521490792669254 
 5385521490420695110    5385521491532181574   5385521491559694406   
5385521491459625030   5385521492275175494  5385521492781318214   
 5385521492710027334    5385521492955615302   5385521493708759110   
5385521494506434630   5385521493104611398

JavaEnable:1      0      1     0      0      0     1      0      1      1    
1      1      1     1      0      1      0     0      1      1

Title:Yandex  Announcements - Investor Relations - Yandex   Yandex — Contact
us — Moscow    Yandex — Mission       Ru      Yandex — History — History of
Yandex   Yandex Financial Releases - Investor Relations - Yandex Yandex
—Locations      Yandex Board of Directors - Corporate Governance- Yandex     
Yandex — Technologies

GoodEvent:1      1      1     1      1      1     1      1      1      1    
1      1      1     1      1      1      1     1      1      1

EventTime:2016-05-18 05:19:20    2016-05-1808:10:20    2016-05-18 07:38:00   
2016-05-1801:13:08    2016-05-18 00:04:06    2016-05-1804:21:30    2016-05-18
00:34:16    2016-05-1807:35:49    2016-05-18 11:41:59    2016-05-18 01:13:32...


这些示例仅显示数据排列的顺序。不同列的值分开存储,同一列的数据一起存储。例如,面向列的DBMS:Vertica,Paraccel(ActianMatrix)(AmazonRedshift),SybaseIQ,Exasol,Infobright,InfiniDB,MonetDB(VectorWise)(ActianVector),LucidDB,SAPHANA,GoogleDremel,GooglePowerDrill,Druid
,kdb +等。

存储数据的不同存储顺序更适合于不同的应用场景。数据访问场景指的是执行什么查询,多长时间查询,每种类型的查询读取多少数据 -
行,列和字节;写取和更新数据之间的关系;数据的大小以及它在本地的使用情况;是否使用交易处理,以及它们是如何隔离的;数据同步和逻辑完整性的要求;每类查询的延迟和吞吐量要求等等。


系统上的负载越高,场景化的系统定制就越重要,定制化就越具体。没有一个系统能够适用于截然不同的应用场景。如果一个系统可以适应多种场景,那么在高负载情况下,系统处理所有场景表现都会很差,或者仅其中一种场景表现良好。

对于OLAP(联机分析处理)方案,将会有如下几种应用场景:

- 绝大多数请求是以读为主。

- 数据以相当大的批次(>1000行)进行更新,而不是单行更新;或者根本不更新。

- 数据被添加到数据库,基本不怎么修改。

- 对于读取,大量的数据从数据库中抽取出来,但只有列的一个子集。

- 表是“宽的”,这意味着它们包含大量的列。

- 查询相对较少(通常每台服务器数百个查询或更少)。

- 对于简单的查询,允许大约50 ms的延迟。

- 列值相当小 - 数字和短字符串(例如,每个URL 60个字节)。

- 处理单个查询时需要高吞吐量(每台服务器每秒高达数十亿行)。

- 无事务处理。

- 数据一致性要求低- 每个查询有一个大表,其他所有的表都是小表。

- 查询结果显著小于源数据。也就是说,数据被过滤或聚合。结果可以放在单个服务器的内存中。


很容易看出,OLAP方案与其他常见方案(如OLTP或Key-Value访问)有很大不同。所以,如果你想获得不错的表现,尝试使用OLTP或Key-ValueDB来处理分析查询是没有意义的。例如,如果您尝试使用MongoDB或Elliptics进行分析,与OLAP数据库相比,您的性能会很差。

面向列的数据库更适合于OLAP方案(对于大多数查询,处理速度至少提高了100倍),原因如下:

1. 对于I/O

2. 对于分析查询,只需要读取少量的列。在面向列的数据库中,您只能读取所需的数据。例如,如果您需要100列中的5列,则I/O可能会减少20倍。

3. 由于数据是以数据包的形式读取的,因此压缩比较容易。列中的数据也更容易压缩。这进一步减少了I/O量。

4. 由于减少的I/O,更多的数据适合在系统缓存中。


例如,查询“统计每个广告平台的记录数量”需要读取一个“广告平台ID”列,其占用1个未压缩字节。如果大多数流量不是来自广告平台,那么您可以期望至少有10倍的压缩比。当使用快速压缩算法时,数据解压缩速度可以达到每秒至少几千兆字节的未压缩数据。换句话说,这个查询可以在一台服务器上以每秒大约几十亿行的速度处理。这个速度实际上是在实践中是容易实现的。

例如:

milovidov@hostname:~$clickhouse-client

ClickHouseclient version 0.0.52053.

Connectingto localhost:9000.

Connectedto ClickHouse server version 0.0.52053.

 

:)SELECT CounterID, count() FROM hits GROUP BY CounterID ORDER BY count()
DESCLIMIT20

 

SELECT

   CounterID,

    count()

FROMhits

GROUP BYCounterID

ORDER BYcount() DESC

LIMIT 20

 

┌─CounterID─┬──count()─┐

│    114208│56057344│

│    115080│51619590│

│      3228│44658301│

│     38230│42045932│

│    145263│42042158│

│     91244│38297270│

│    154139│26647572│

│    150748│24112755│

│    242232│21302571│

│    338158│13507087│

│     62180│12229491│

│     82264│12187441│

│    232261│12148031│

│    146272│11438516│

│    168777│11403636│

│   4120072│11227824│

│  10938808│10519739│

│     74088│  9047015│

│    115079│  8837972│

│    337234│  8205961│

└───────────┴──────────┘

 

20 rows in set. Elapsed: 0.153 sec. Processed 1.00 billion rows, 4.00 GB (6.53
billion rows/s.,26.10 GB/s.)

 

1.     对于CPU


由于执行查询需要处理大量的行,因此它有助于为整个向量调度所有操作,而不是单独的行,或者实现查询引擎,这样就几乎没有调度成本。如果你不这样做,任何半象限的磁盘子系统(half-decent
disk subsystem),查询解释器不可避免地中断(阻塞)CPU。将数据存储在列中并在可能的情况下按列处理是有意义的。

有两种方法可以做到这一点:

1. 向量引擎(A vector
engine)。所有的操作都是为向量而写的,而不是单独的值。这意味着您不需要经常调用操作,调度成本可以忽略不计。操作代码包含一个优化的内部循环。

2. 代码生成(Code generation)。为查询生成的代码具有所有的间接调用。


这不是在“普通”数据库中完成的,因为运行简单查询时没有意义。但是,也有例外。例如,MemSQL在处理SQL查询时使用代码生成来减少延迟。(为了比较,分析DBMS需要优化吞吐量,而不是延迟。)

请注意,为了提高CPU效率,查询语言必须是声明式的(SQL或MDX),或者至少是一个向量(J,K)。查询应该只包含隐式循环,以便优化。

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信