时间序列案例

许多记录和时间相关。当你有数百万记录时,索引开始出现明显的不足,因为寻找记录的时间复杂度为O(logN)。这也是关系数据库在海量数据下慢的原因。

所以,当你拥有数百万记录时,最好的方式是线性扩展来避免使用全部的索引。但是可以不使用索引在较短的时间内查询记录吗?OrientDB每次查询都遍历全部的数据库吗?当然不是,你可以利用OrientDB的属性。来看一个简单的例子,说下日志。

一条典型的日志记录包含了同样的信息:日期和事件。下面是我们在例子中使用的日志记录。我们将使用JSON格式来简化阅读:

{
  "date" : 12293289328932,
  "priority" : "critical",
  "note" : "System reboot"
}

现在我们创建一棵树(有向无环图)来讲日志记录按照我们需要的粒度去聚合:

Year -> month (map) -> Month -> day (map) -> Day -> hour  (map) -> Hour

年月日都是顶点类。每个顶点连接其他较小类型的顶点。连接使用Map来方便查询。

创建类:

CREATE CLASS Year
CREATE CLASS Month
CREATE CLASS Day
CREATE CLASS Hour

CREATE PROPERTY Year.month LINKMAP Month
CREATE PROPERTY Month.day LINKMAP Day
CREATE PROPERTY Day.hour LINKMAP Hour

检索2012年3月20号上午10点的顶点:

SELECT month[3].day[20].hour[10].logs FROM Year WHERE year = "2012"

如果需要更细的粒度,可以继续向下连接:

Hour -> minute (map) -> Minute -> second (map) -> Second

现在将记录绑定到正确的日期顶点上。如果通常检索的方式是按照小时,那么你可以把日志记录存储到小时顶点上。例如:

Year -> month (map) -> Month -> day (map) -> Day -> hour  (map) -> Hour -> log (set) -> Log

"log"属性连接了时间单元和真实的记录。所以检索2012年3月20号上午10点的所有记录,如下:

SELECT expand( month[3].day[20].hour[10].logs ) FROM Year WHERE year = "2012"

上述的例子将被用来作为根据特定规则检索日志子集的起点。例如如下:

SELECT FROM (
  SELECT expand( month[3].day[20].hour[10].logs ) FROM Year WHERE year = "2012"
) WHERE priority = 'critical'

检索检索2012年3月20号上午10点所有重要的记录。

查询多个小时段

如果需要查询多个小时/天/月,可以使用UNION函数来创建一个唯一的结果集:

SELECT expand( records ) from (
  SELECT union( month[3].day[20].hour[10].logs, month[3].day[20].hour[11].logs ) AS records
  FROM Year WHERE year = "2012"
)

在这个例子中,我们查询了10点和11点的日志。如果想查询一天的记录,不需要写一个大的查询。最简短的方式就是遍历(Traverse)。下面就是遍历一天的所有小时:

TRAVERSE hour FROM (
  SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
)

把查询放在一起就能查询一天所有小时的记录:

SELECT expand( logs ) FROM (
  SELECT union( logs ) AS logs FROM (
    TRAVERSE hour FROM (
     SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
    )
  )
)

聚合

如果想建立一个图的日历来存储聚合的值然后把它对应到时间单元。例如:存储在线游戏赢得的券。记录的结构如下:

{
  "date" : 12293289328932,
  "win" : 10.34,
  "machine" : "AKDJKD7673JJSH",
}

你可以把记录连接到最近的时间单元中,但是你可以汇总同一天的记录和关联到天的顶点中。例如:

创建一个存储每日聚合的记录:

CREATE CLASS DailyLog

从小时的聚合创建记录:

INSERT INTO DailyLog
SET win = (
  SELECT SUM(win) AS win FROM Hour WHERE date BETWEEN '2012-03-20 10:00:00' AND '2012-03-20 11:00:00'
)

如上上面的命令返回的DailyLog记录的RID是#23:45,通过下面语句将聚合的记录值存储到对应的天的顶点上:

UPDATE (
  SELECT expand( month[3].day[20] ) FROM Year WHERE year = "2012"
) ADD logs = #23:45