利用可排序Key-Value DB构建时间序列数据库(简论)
2016-09-09 00:44
363 查看
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/5855064.html
本文使用LevelDB,HBase这类列式存KV储数据来构建时间序列数据库。
物体有一些静态属性。静态属性不随时间发送变化。时间序列数据一般不关注静态属性。
还有一些动态属性。动态属性的值会随时间发送变化,一般的动态属性被称为指标。指标的名称即metricName。
物体与指标都具有名称。而名称字符串应该与一个无符号整数映射起来。即存储ObjectName与ObjectId的对应关系。
Data
使用SSTable存储KV型数据。支持Scan查询。存储Key与Value的关系。
查询一段时间([timestamp0,timestam1])内某个object的所有metric的值。 ==> 抽象成函数即 query( objectId , timestamp0 , timestamp1 )
查询一段时间([timestamp0,timestam1])内某个object的某个metric的值。 ==> 抽象成函数即 query( objectId , metricId , timestamp0 , timestamp1 )
查询一段时间内所有object的某个metric的值。 == > 抽象成函数即 query( metricId , timestamp0 , timestamp1 )
查询一段时间内所有object的所有metric的值。 == > 抽象成函数即 query( timestamp0 , timestamp1 )
一般的 query( objectId , metricId , timestamp0 , timestamp1 ) 这种查询更为常见。
timestamp | objectId | metricId
数据按时间顺序排序。是一种比较合理的构造方法,适合object较少的情况。
方法2:
timestamp | metricId | objectId
与方法1的应用场景一致。适合object较少的情况。且适合指定metricId的查询。
方法3:
objectId | timestamp | metricId
可以方便的查询,查询一段时间([timestamp0,timestam1])内某个object的所有指标值。即:query( objectId , timestamp0 , timestam1 )
但对一段时间([timestamp0,timestam1])内某个object的某个metric值,性能会稍显不足。这是因为在查询过程中需要过滤掉非指定metricId的指标。
比如一个object有30个metric,当前只需要查询object的metric1。则需要跳过{metric2 , metric3 , ...... , metric30 }的值。效率明显降低了。
方法4:
objectId | metricId | timestamp
可以方便查询一段时间([timestamp0,timestam1])内某个object的某个metric值。
但是如果需要查询一段时间([timestamp0,timestam1])内某个object的所有指标值,就会有所困难。
方法5:
改进方法4:在Meta中记录每个objectId与metricId的映射关系。即需要增加一张Mapping表。
查询一段时间([timestamp0,timestam1])内某个object的所有指标值,需要先从Mapping表中查询objectId具有的metricIds集合:
objectId ==> {metric1,metric2,metric3,metric4,...metricN}
然后按照对每一个metricId进行查询:
query( objectId , metric1 , [timestamp0,timestam1] )
query( objectId , metric2 , [timestamp0,timestam1] )
query( objectId , metric3 , [timestamp0,timestam1] )
......
query( objectId , metricN , [timestamp0,timestam1] )
查询后,把各个merge起来。
静态数值类型
存储前,定义存储格式,并记录下来。存储时按照定义的存储格式进行序列化。类似于MySQL的使用方式。
动态数值类型
在数值序列化成byte[]后,用1个byte标记数值类型。并将整个byte添加到byte[]之前。合一起后存储下来。
即: typeByte | valueBytes
读取数值时,按照第一个typeByte的值来解析后面的byte[]。
动态数值类型更加灵活,但每一条数据都需要多存储1个byte的额外信息。对于静态数值类型,会造成存储空间的浪费。
ObjectMeta表
objectName-objectId
MetricMeta表
metricName-metricId
ObjectMetricMeta表
objectId-metricId
静态层存储
业务层存储(不存在于时间序列数据库中)
staitcData
objectId-metricId-value
动态属性值存储
objectId|metricId|timestamp <--> (valueType) value
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/5855064.html
http://www.cnblogs.com/shijiaqi1066/p/5855064.html
本文使用LevelDB,HBase这类列式存KV储数据来构建时间序列数据库。
时间序列数据的特征
经典物理世界,若需要进行测量,则首先需要标注出来。所以首先物体需要有一个ObjectName。物体有一些静态属性。静态属性不随时间发送变化。时间序列数据一般不关注静态属性。
还有一些动态属性。动态属性的值会随时间发送变化,一般的动态属性被称为指标。指标的名称即metricName。
基础表
Meta物体与指标都具有名称。而名称字符串应该与一个无符号整数映射起来。即存储ObjectName与ObjectId的对应关系。
Data
使用SSTable存储KV型数据。支持Scan查询。存储Key与Value的关系。
时间序列数据库的查询需求
在不考虑聚合问题的前提下,一般的时间序列数据的查询有以下需求:查询一段时间([timestamp0,timestam1])内某个object的所有metric的值。 ==> 抽象成函数即 query( objectId , timestamp0 , timestamp1 )
查询一段时间([timestamp0,timestam1])内某个object的某个metric的值。 ==> 抽象成函数即 query( objectId , metricId , timestamp0 , timestamp1 )
查询一段时间内所有object的某个metric的值。 == > 抽象成函数即 query( metricId , timestamp0 , timestamp1 )
查询一段时间内所有object的所有metric的值。 == > 抽象成函数即 query( timestamp0 , timestamp1 )
一般的 query( objectId , metricId , timestamp0 , timestamp1 ) 这种查询更为常见。
Key的构造
方法1:timestamp | objectId | metricId
数据按时间顺序排序。是一种比较合理的构造方法,适合object较少的情况。
方法2:
timestamp | metricId | objectId
与方法1的应用场景一致。适合object较少的情况。且适合指定metricId的查询。
方法3:
objectId | timestamp | metricId
可以方便的查询,查询一段时间([timestamp0,timestam1])内某个object的所有指标值。即:query( objectId , timestamp0 , timestam1 )
但对一段时间([timestamp0,timestam1])内某个object的某个metric值,性能会稍显不足。这是因为在查询过程中需要过滤掉非指定metricId的指标。
比如一个object有30个metric,当前只需要查询object的metric1。则需要跳过{metric2 , metric3 , ...... , metric30 }的值。效率明显降低了。
方法4:
objectId | metricId | timestamp
可以方便查询一段时间([timestamp0,timestam1])内某个object的某个metric值。
但是如果需要查询一段时间([timestamp0,timestam1])内某个object的所有指标值,就会有所困难。
方法5:
改进方法4:在Meta中记录每个objectId与metricId的映射关系。即需要增加一张Mapping表。
查询一段时间([timestamp0,timestam1])内某个object的所有指标值,需要先从Mapping表中查询objectId具有的metricIds集合:
objectId ==> {metric1,metric2,metric3,metric4,...metricN}
然后按照对每一个metricId进行查询:
query( objectId , metric1 , [timestamp0,timestam1] )
query( objectId , metric2 , [timestamp0,timestam1] )
query( objectId , metric3 , [timestamp0,timestam1] )
......
query( objectId , metricN , [timestamp0,timestam1] )
查询后,把各个merge起来。
数值存储
数据存储于磁盘上都是以字节数组存储的。当读出来时需要知道存储时的数据格式。所以,需要把存储时的值格式记录下来。静态数值类型
存储前,定义存储格式,并记录下来。存储时按照定义的存储格式进行序列化。类似于MySQL的使用方式。
动态数值类型
在数值序列化成byte[]后,用1个byte标记数值类型。并将整个byte添加到byte[]之前。合一起后存储下来。
即: typeByte | valueBytes
读取数值时,按照第一个typeByte的值来解析后面的byte[]。
动态数值类型更加灵活,但每一条数据都需要多存储1个byte的额外信息。对于静态数值类型,会造成存储空间的浪费。
设计一个完整的时间序列数据库
元信息层ObjectMeta表
objectName-objectId
MetricMeta表
metricName-metricId
ObjectMetricMeta表
objectId-metricId
静态层存储
业务层存储(不存在于时间序列数据库中)
staitcData
objectId-metricId-value
动态属性值存储
objectId|metricId|timestamp <--> (valueType) value
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/5855064.html
相关文章推荐
- 利用建站快速软件包:XAMPP,构建基于winodws平台快速搭建PHP的数据库应用- kimai - 团队时间记录
- Oracle使用序列及使用数据库时间
- 利用NetBeans构建一个 Java 桌面数据库应用程序
- pl/sql利用rownum取得排序后的部分行序列
- 利用ArrayCollection获取数据库的信息构建多级树结构
- android一个很好的数据库基类,利用此类非常方便构建数据库操作类
- 昨天写了利用时间序列搜索方法预测股票价格程序
- R工具:连接数据库,查数据,画时间序列图,加点、文本
- 餐馆联邦一次运行的时间推进序列 (按时间排序的时间推进请求和time grant序列)
- Oracle10g利用rownum取得排序后的部分行序列
- Oracle利用构建DataTable分批量Insert或Update至数据库
- Delphi 利用TStringList 构建简单数据库
- 利用NetBeans构建一个 Java 桌面数据库应用程序
- 利用NetBeans构建一个 Java 桌面数据库应用程序
- 一个很好的数据库基类,利用此类非常方便构建数据库操作类
- 利用timestamp实现数据库处理同一记录的时间差异问题
- 利用NetBeans构建一个 Java 桌面数据库应用程序
- 利用 Oracle 数据库 10g、Oracle Discoverer 和 Oracle Portal 构建 BI 信息板
- 利用excel对记事进行时间排序
- sqlserver存储过程中利用游标遍历结果集简单示例及查询数据库时间