time-based DB

这类时间序列数据库最多,使用也最广泛。一般人们谈论时间序列数据库的时候指代的就是这一类存储。按照底层技术不同可以划分为三类。

我们希望时间序列数据库不仅仅可以提供原始数据的查询,而且要支持对原始数据的聚合能力。这种聚合可以是在入库阶段完成的,所谓物化视图。也可以是在查询阶段完成,所谓实时聚合。根据实际情况,可以在这两种方式中进行取舍。

想要在在查询阶段做数据的聚合和转换,需要能够支持以下三点。

  • 用索引检索出行号:能够从上亿条数据中快速过滤出几百万的数据。
  • 从主存储按行号加载:能够快速加载这过滤出的几百万条数据到内存里。
  • 分布式计算:能够把这些数据按照GROUP BY 和 SELECT 的要求计算出最终的结果集。

要想尽可能快的完成整个查询过程,需要在三个环节上都有绝招。传统上说,这三个步骤是三个不同的技术领域。

  • 检索:这是搜索引擎最擅长的领域。代表产品是Lucene。其核心技术是基于高效率数据结构和算法的倒排索引。
  • 加载:这是分析型数据库最擅长的领域。代表产品是C-storeMonetdb。其核心技术是按列组织的磁盘存储结构。
  • 分布式计算:这是大数据计算引擎最擅长的领域。代表产品是Hadoopspark。其核心技术是sharding 和 map/reduce等等。

现在我们可以回答“为什么Elasticsearch/Lucene检索可以比mysql快了。Mysql只有term dictionary这一层,是以b-tree排序的方式存储在磁盘上的。检索一个term需要若干次的random access的磁盘操作。而Lucene在term dictionary的基础上添加了term index来加速检索,term index以树的形式缓存在内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘的random access次数。

额外值得一提的两点是:term index在内存中是以FST(finite state transducers)的形式保存的,其特点是非常节省内存。Term dictionary在磁盘上是以分block的方式保存的,一个block内部利用公共前缀压缩,比如都是Ab开头的单词就可以把Ab省去。这样term dictionary可以比b-tree更节约磁盘空间。

分布式聚合如何做得快

Elasticsearch/Lucene从最底层就支持数据分片,查询的时候可以自动把不同分片的查询结果合并起来。Elasticsearch的document都有一个uid,默认策略是按照uid 的 hash把文档进行分片。

一个Elasticsearch Index相当于一个MySQL里的表,不同Index的数据是物理上隔离开来的。Elasticsearch的Index会分成多个Shard存储,一部分Shard是Replica备份。一个Shard是一份本地的存储(一个本地磁盘上的目录),也就是一个Lucene的Index。不同的Shard可能会被分配到不同的主机节点上。一个Lucene Index会存储很多的doc,为了好管理,Lucene把Index再拆成了Segment存储(子目录)。Segment内的doc数量上限是1的31次方,这样doc id就只需要一个int就可以存储。Segment对应了一些列文件存储索引(倒排表等)和主存储(DocValues等),这些文件内部又分为小的Block进行压缩。

时间序列数据一般按照日期分成多个Elasticsearch Index来存储,比如logstash-2014.08.02。查询的时候可以指定多个Elasticsearch Index作为查找的范围,也可以用logstash-*做模糊匹配

上一篇:使用fileupload组件


下一篇:.NET开源论坛MvcForum推荐