OSISoft实时/历史数据库PI的数据存储机制分析

来源:互联网 发布:音乐相册软件哪个好 编辑:程序博客网 时间:2024/05/01 06:03
    实时/历史数据库PI的大名想必很多人都听过,在国内很多电厂的SIS系统都是用PI做的。PI在实时/历史数据库领域是做的最为成功的,但同时价格也是最高的,动辄几十万甚至上百万的价格让很多中小企业是望而却步,但听说最近OSISoft公司又提高了PI的价格,真是牛啊!
    前一段时间因为工作需要,对PI的历史数据存储机制做了一些分析之后,大体弄明白了PI是如何存储历史数据的,一些以前无法想明白的问题也找到了答案。例如,在PI的很多文档上都提到了,存储一条32位浮点型的变量的记录平均只需5个字节,以前就很难想明白PI是怎么做到的。因为一条记录至少需要包含三个字段VQT(V:Value,指变量值;Q:Quality,指数据质量;T:Timestamp,指变量值对应的时间戳),对于32位浮点型变量而言,变量值V就需要4个字节存储,这就意味着Q和T平均只占用一个字节,这几乎不可能,但是PI做到了,接下来我们就来具体看看PI是如何做到这点的。
   需要声明的是,我所做的分析是根据PI的windows版本(V3.4)所做的,所以分析结论并不完全适用于其他操作系统平台下的PI版本(例如在Unix系统下的缓存实现机制),如果哪位朋友有这方面的心得体会,也希望能拿出来跟大家分享一下,我也乐意就本文内容以及任何与实时/历史数据库相关的问题与大家进行交流。
    首先简单介绍一下PI的历史数据文件的基本格式,PI的历史数据都存储在形如piarch.001这样的数据文件中,与之相对应的还有一个形如piarch.001.ann这样的文件,后者是用来存储针对变量记录的注释用的,一般很少使用,我也未做分析。对于形如piarch.001这样的数据文件内部,PI采用的是分块(分页)的管理方式,每块(页)的大小为1024字节,这实质上隐含限制了一条变量记录的长度是不可能超过1000字节的。页从文件开头开始编号,第一个页号为0,用于存储跟文件相关的信息。之后的页就用于存储变量历史数据,每个变量初始被分配一个页用于存储数据,随着记录的追加,更多的页被分配给变量,当页数多余3时(根据我的观察)时,PI采用如下的数据结构来组织变量数据(图1)。


   
                            图1 PI的历史数据存储结构

    从图1可以看到,PI采用的是一种两层的简单存储结构,而不是大家通常想象的多层树型结构(例如B+树)。每一层相邻的两个页之间是互相链接在一起的,同时叶子节点(记录节点)也维护到父节点(索引节点)的反向引用指针。在索引节点上存储的记录是每个记录节点的起始时间和对应的页号。这样的存储结构有什么优点、有什么缺点,相信大家都是一目了然,我就不多说了。
    接下来说说每个页(块)内的数据组织,前面已经说过每个页的大小为1024字节,除去30字节左右的固定页头(不同数据类型的页头会有细微差别,但都包含以下信息:变量ID、当前页号、上一页号、下一页号、父页号、是否为索引节点标志、记录条数、起始时间戳等),每个页用于存储历史数据的有效空间为990个字节左右。
    对于历史记录的存储,PI最核心的理念就是“不顾一切的尽可能缩减存储记录所需要的磁盘空间”,为了达到这个目标,PI采用的是变长记录的存储方式(注意:没有关系数据库里面的所谓行偏移数组),而且还不惜牺牲时间精度。对于时间戳T的存储,PI采用的是差分法,即只存储与前一条记录的时间戳之差值,如果这个差值能够用一个字节表示(通常单位为秒,不过依据PI的文档,好像还可能是更大的单位),那么这个时间戳T就只需用一个字节表示;如果无法用一个字节表示,或者差值小于1秒,则使用多个字节表示(2~5?)。对于质量戳Q的存储,PI的策略是如果该质量戳是好的(GOOD),则不存;即只存坏质量戳,这通常意味着对于99.99%的数据记录而言,不需要存储质量戳。相信大家现在都已经明白了,前面的存储一条32位浮点变量记录平均只需5个字节是怎么做到的了。
    以下几个图是根据以上分析结论所做的测试结果:

                图2  索引节点的记录(时间戳:页号)

 
                图3 叶子节点的记录(时间戳:变量值)

      
              图4 时间精度小于1秒的情形

    说完了PI的历史数据存储结构之后,最后再来简单说说PI的缓存实现机制(Windows平台)。根据我的实验观察结果,  我的结论是windows 平台下的PI归档系统(Archive System)并没有自己实现的缓存机制,而是直接利用的操作系统的文件系统缓存。这样的好处当然是实现简单,而且操作系统的文件缓存系统是一个能够动态扩展或者缩减的系统,能自适应环境的变化。缺点当然也很明显,那就是无法对缓存的页面进行更精细的控制(如要求其始终停留在内存中或者强制刷新某页或者进行优先级控制),而且很容易受其他程序的干扰(例如文件拷贝)。我们在实际中遇到的一个例子是:连续不断的读取PI历史数据,最后导致PI系统不能正常归档,应该就是由于此缓存机制导致的(连续读操作造成写缓存失效)。

原创粉丝点击